Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
716 | lvd | 1 | /* |
2 | ** |
||
3 | ** File: fm.c -- software implementation of Yamaha FM sound generator |
||
4 | ** |
||
5 | ** Copyright (C) 2001, 2002, 2003 Jarek Burczynski (bujar at mame dot net) |
||
6 | ** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmulator development |
||
7 | ** |
||
8 | ** Version 1.4A (final beta) |
||
9 | ** |
||
10 | */ |
||
11 | |||
12 | /* |
||
13 | ** History: |
||
14 | ** |
||
15 | ** 14-02-2006 Alone Coder: |
||
16 | ** - fixed YM2203 stop volume (511 instead of MAX_ATT_INDEX) - verified on real chip |
||
17 | ** - fixed YM2203 SSG-EG=#0a key off (inversion disabled) - verified on real chip |
||
18 | ** - uncommented sine generator in SSG-EG reinit - verified on real chip |
||
19 | ** |
||
20 | ** 03-08-2003 Jarek Burczynski: |
||
21 | ** - fixed YM2608 initial values (after the reset) |
||
22 | ** - fixed flag and irqmask handling (YM2608) |
||
23 | ** - fixed BUFRDY flag handling (YM2608) |
||
24 | ** |
||
25 | ** 14-06-2003 Jarek Burczynski: |
||
26 | ** - implemented all of the YM2608 status register flags |
||
27 | ** - implemented support for external memory read/write via YM2608 |
||
28 | ** - implemented support for deltat memory limit register in YM2608 emulation |
||
29 | ** |
||
30 | ** 22-05-2003 Jarek Burczynski: |
||
31 | ** - fixed LFO PM calculations (copy&paste bugfix) |
||
32 | ** |
||
33 | ** 08-05-2003 Jarek Burczynski: |
||
34 | ** - fixed SSG support |
||
35 | ** |
||
36 | ** 22-04-2003 Jarek Burczynski: |
||
37 | ** - implemented 100% correct LFO generator (verified on real YM2610 and YM2608) |
||
38 | ** |
||
39 | ** 15-04-2003 Jarek Burczynski: |
||
40 | ** - added support for YM2608's register 0x110 - status mask |
||
41 | ** |
||
42 | ** 01-12-2002 Jarek Burczynski: |
||
43 | ** - fixed register addressing in YM2608, YM2610, YM2610B chips. (verified on real YM2608) |
||
44 | ** The addressing patch used for early Neo-Geo games can be removed now. |
||
45 | ** |
||
46 | ** 26-11-2002 Jarek Burczynski, Nicola Salmoria: |
||
47 | ** - recreated YM2608 ADPCM ROM using data from real YM2608's output which leads to: |
||
48 | ** - added emulation of YM2608 drums. |
||
49 | ** - output of YM2608 is two times lower now - same as YM2610 (verified on real YM2608) |
||
50 | ** |
||
51 | ** 16-08-2002 Jarek Burczynski: |
||
52 | ** - binary exact Envelope Generator (verified on real YM2203); |
||
53 | ** identical to YM2151 |
||
54 | ** - corrected 'off by one' error in feedback calculations (when feedback is off) |
||
55 | ** - corrected connection (algorithm) calculation (verified on real YM2203 and YM2610) |
||
56 | ** |
||
57 | ** 18-12-2001 Jarek Burczynski: |
||
58 | ** - added SSG-EG support (verified on real YM2203) |
||
59 | ** |
||
60 | ** 12-08-2001 Jarek Burczynski: |
||
61 | ** - corrected sin_tab and tl_tab data (verified on real chip) |
||
62 | ** - corrected feedback calculations (verified on real chip) |
||
63 | ** - corrected phase generator calculations (verified on real chip) |
||
64 | ** - corrected envelope generator calculations (verified on real chip) |
||
65 | ** - corrected FM volume level (YM2610 and YM2610B). |
||
66 | ** - changed YMxxxUpdateOne() functions (YM2203, YM2608, YM2610, YM2610B, YM2612) : |
||
67 | ** this was needed to calculate YM2610 FM channels output correctly. |
||
68 | ** (Each FM channel is calculated as in other chips, but the output of the channel |
||
69 | ** gets shifted right by one *before* sending to accumulator. That was impossible to do |
||
70 | ** with previous implementation). |
||
71 | ** |
||
72 | ** 23-07-2001 Jarek Burczynski, Nicola Salmoria: |
||
73 | ** - corrected YM2610 ADPCM type A algorithm and tables (verified on real chip) |
||
74 | ** |
||
75 | ** 11-06-2001 Jarek Burczynski: |
||
76 | ** - corrected end of sample bug in ADPCMA_calc_cha(). |
||
77 | ** Real YM2610 checks for equality between current and end addresses (only 20 LSB bits). |
||
78 | ** |
||
79 | ** 08-12-98 hiro-shi: |
||
80 | ** rename ADPCMA -> ADPCMB, ADPCMB -> ADPCMA |
||
81 | ** move ROM limit check.(CALC_CH? -> 2610Write1/2) |
||
82 | ** test program (ADPCMB_TEST) |
||
83 | ** move ADPCM A/B end check. |
||
84 | ** ADPCMB repeat flag(no check) |
||
85 | ** change ADPCM volume rate (8->16) (32->48). |
||
86 | ** |
||
87 | ** 09-12-98 hiro-shi: |
||
88 | ** change ADPCM volume. (8->16, 48->64) |
||
89 | ** replace ym2610 ch0/3 (YM-2610B) |
||
90 | ** change ADPCM_SHIFT (10->8) missing bank change 0x4000-0xffff. |
||
91 | ** add ADPCM_SHIFT_MASK |
||
92 | ** change ADPCMA_DECODE_MIN/MAX. |
||
93 | */ |
||
94 | |||
95 | |||
96 | |||
97 | |||
98 | /************************************************************************/ |
||
99 | /* comment of hiro-shi(Hiromitsu Shioya) */ |
||
100 | /* YM2610(B) = OPN-B */ |
||
101 | /* YM2610 : PSG:3ch FM:4ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */ |
||
102 | /* YM2610B : PSG:3ch FM:6ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */ |
||
103 | /************************************************************************/ |
||
104 | |||
105 | //fnum= fq*2.3575 |
||
106 | /* globals */ |
||
107 | #include "std.h" |
||
108 | #include "sysdefs.h" |
||
109 | #include "emul_2203.h" |
||
110 | |||
111 | #define TYPE_SSG 0x01 /* SSG support */ |
||
112 | #define TYPE_LFOPAN 0x02 /* OPN type LFO and PAN */ |
||
113 | #define TYPE_6CH 0x04 /* FM 6CH / 3CH */ |
||
114 | #define TYPE_DAC 0x08 /* YM2612's DAC device */ |
||
115 | #define TYPE_ADPCM 0x10 /* two ADPCM units */ |
||
116 | |||
117 | #define TYPE_YM2203 (TYPE_SSG) |
||
118 | #define TYPE_YM2608 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM) |
||
119 | #define TYPE_YM2610 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM) |
||
120 | #define TYPE_YM2612 (TYPE_DAC |TYPE_LFOPAN |TYPE_6CH) |
||
121 | |||
122 | #define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */ |
||
123 | #define EG_SH 16 /* 16.16 fixed point (envelope generator timing) */ |
||
124 | #define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */ |
||
125 | #define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */ |
||
126 | |||
127 | #define FREQ_MASK ((1<<FREQ_SH)-1) |
||
128 | |||
129 | #define ENV_BITS 10 |
||
130 | #define ENV_LEN (1<<ENV_BITS) |
||
131 | #define ENV_STEP (128.0/ENV_LEN) |
||
132 | |||
133 | #define MAX_ATT_INDEX (ENV_LEN-1) /* 1023 */ |
||
134 | #define MIN_ATT_INDEX (0) /* 0 */ |
||
135 | |||
136 | #define EG_ATT 4 |
||
137 | #define EG_DEC 3 |
||
138 | #define EG_SUS 2 |
||
139 | #define EG_REL 1 |
||
140 | #define EG_OFF 0 |
||
141 | |||
142 | #define SIN_BITS 10 |
||
143 | #define SIN_LEN (1<<SIN_BITS) |
||
144 | #define SIN_MASK (SIN_LEN-1) |
||
145 | |||
146 | #define TL_RES_LEN (256) /* 8 bits addressing (real chip) */ |
||
147 | |||
148 | #if (FM_SAMPLE_BITS==16) |
||
149 | #define FINAL_SH (0) |
||
150 | #define MAXOUT (+32767) |
||
151 | #define MINOUT (-32768) |
||
152 | #else |
||
153 | #define FINAL_SH (8) |
||
154 | #define MAXOUT (+127) |
||
155 | #define MINOUT (-128) |
||
156 | #endif |
||
157 | |||
158 | /* TL_TAB_LEN is calculated as: |
||
159 | * 13 - sinus amplitude bits (Y axis) |
||
160 | * 2 - sinus sign bit (Y axis) |
||
161 | * TL_RES_LEN - sinus resolution (X axis) |
||
162 | */ |
||
163 | #define TL_TAB_LEN (13*2*TL_RES_LEN) |
||
164 | |||
165 | #define ENV_QUIET (TL_TAB_LEN>>3) |
||
166 | |||
167 | #define RATE_STEPS (8) |
||
168 | |||
169 | #define INTERNAL_TIMER_A(ST,CSM_CH) |
||
170 | #define INTERNAL_TIMER_B(ST,step) |
||
171 | |||
172 | #define logerror(a,b,c,d,e) |
||
173 | |||
174 | #define SC(db) (UINT32) ( db * (4.0/ENV_STEP) ) |
||
175 | static const UINT32 sl_table[16]={ |
||
176 | SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7), |
||
177 | SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31) |
||
178 | }; |
||
179 | #undef SC |
||
180 | |||
181 | static const UINT8 eg_inc[19*RATE_STEPS]={ |
||
182 | |||
183 | /*cycle:0 1 2 3 4 5 6 7*/ |
||
184 | |||
185 | /* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..11 0 (increment by 0 or 1) */ |
||
186 | /* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..11 1 */ |
||
187 | /* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..11 2 */ |
||
188 | /* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..11 3 */ |
||
189 | |||
190 | /* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 12 0 (increment by 1) */ |
||
191 | /* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 12 1 */ |
||
192 | /* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 12 2 */ |
||
193 | /* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 12 3 */ |
||
194 | |||
195 | /* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 13 0 (increment by 2) */ |
||
196 | /* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 13 1 */ |
||
197 | /*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 13 2 */ |
||
198 | /*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 13 3 */ |
||
199 | |||
200 | /*12 */ 4,4, 4,4, 4,4, 4,4, /* rate 14 0 (increment by 4) */ |
||
201 | /*13 */ 4,4, 4,8, 4,4, 4,8, /* rate 14 1 */ |
||
202 | /*14 */ 4,8, 4,8, 4,8, 4,8, /* rate 14 2 */ |
||
203 | /*15 */ 4,8, 8,8, 4,8, 8,8, /* rate 14 3 */ |
||
204 | |||
205 | /*16 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */ |
||
206 | /*17 */ 16,16,16,16,16,16,16,16, /* rates 15 2, 15 3 for attack */ |
||
207 | /*18 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */ |
||
208 | }; |
||
209 | |||
210 | #define O(a) (a*RATE_STEPS) |
||
211 | |||
212 | /*note that there is no O(17) in this table - it's directly in the code */ |
||
213 | static const UINT8 eg_rate_select[32+64+32]={ /* Envelope Generator rates (32 + 64 rates + 32 RKS) */ |
||
214 | /* 32 infinite time rates */ |
||
215 | O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), |
||
216 | O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), |
||
217 | O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), |
||
218 | O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), |
||
219 | |||
220 | /* rates 00-11 */ |
||
221 | O( 0),O( 1),O( 2),O( 3), |
||
222 | O( 0),O( 1),O( 2),O( 3), |
||
223 | O( 0),O( 1),O( 2),O( 3), |
||
224 | O( 0),O( 1),O( 2),O( 3), |
||
225 | O( 0),O( 1),O( 2),O( 3), |
||
226 | O( 0),O( 1),O( 2),O( 3), |
||
227 | O( 0),O( 1),O( 2),O( 3), |
||
228 | O( 0),O( 1),O( 2),O( 3), |
||
229 | O( 0),O( 1),O( 2),O( 3), |
||
230 | O( 0),O( 1),O( 2),O( 3), |
||
231 | O( 0),O( 1),O( 2),O( 3), |
||
232 | O( 0),O( 1),O( 2),O( 3), |
||
233 | |||
234 | /* rate 12 */ |
||
235 | O( 4),O( 5),O( 6),O( 7), |
||
236 | |||
237 | /* rate 13 */ |
||
238 | O( 8),O( 9),O(10),O(11), |
||
239 | |||
240 | /* rate 14 */ |
||
241 | O(12),O(13),O(14),O(15), |
||
242 | |||
243 | /* rate 15 */ |
||
244 | O(16),O(16),O(16),O(16), |
||
245 | |||
246 | /* 32 dummy rates (same as 15 3) */ |
||
247 | O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), |
||
248 | O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), |
||
249 | O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), |
||
250 | O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16) |
||
251 | |||
252 | }; |
||
253 | #undef O |
||
254 | |||
255 | #define O(a) (a*1) |
||
256 | static const UINT8 eg_rate_shift[32+64+32]={ /* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */ |
||
257 | /* 32 infinite time rates */ |
||
258 | O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), |
||
259 | O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), |
||
260 | O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), |
||
261 | O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), |
||
262 | |||
263 | /* rates 00-11 */ |
||
264 | O(11),O(11),O(11),O(11), |
||
265 | O(10),O(10),O(10),O(10), |
||
266 | O( 9),O( 9),O( 9),O( 9), |
||
267 | O( 8),O( 8),O( 8),O( 8), |
||
268 | O( 7),O( 7),O( 7),O( 7), |
||
269 | O( 6),O( 6),O( 6),O( 6), |
||
270 | O( 5),O( 5),O( 5),O( 5), |
||
271 | O( 4),O( 4),O( 4),O( 4), |
||
272 | O( 3),O( 3),O( 3),O( 3), |
||
273 | O( 2),O( 2),O( 2),O( 2), |
||
274 | O( 1),O( 1),O( 1),O( 1), |
||
275 | O( 0),O( 0),O( 0),O( 0), |
||
276 | |||
277 | /* rate 12 */ |
||
278 | O( 0),O( 0),O( 0),O( 0), |
||
279 | |||
280 | /* rate 13 */ |
||
281 | O( 0),O( 0),O( 0),O( 0), |
||
282 | |||
283 | /* rate 14 */ |
||
284 | O( 0),O( 0),O( 0),O( 0), |
||
285 | |||
286 | /* rate 15 */ |
||
287 | O( 0),O( 0),O( 0),O( 0), |
||
288 | |||
289 | /* 32 dummy rates (same as 15 3) */ |
||
290 | O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), |
||
291 | O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), |
||
292 | O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), |
||
293 | O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0) |
||
294 | }; |
||
295 | #undef O |
||
296 | |||
297 | static const UINT8 dt_tab[4 * 32]={ |
||
298 | /* this is YM2151 and YM2612 phase increment data (in 10.10 fixed point format)*/ |
||
299 | /* FD=0 */ |
||
300 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||
301 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||
302 | /* FD=1 */ |
||
303 | 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, |
||
304 | 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8, |
||
305 | /* FD=2 */ |
||
306 | 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, |
||
307 | 5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16, |
||
308 | /* FD=3 */ |
||
309 | 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, |
||
310 | 8 , 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22 |
||
311 | }; |
||
312 | |||
313 | /* register number to channel number , slot offset */ |
||
314 | #define OPN_CHAN(N) (N&3) |
||
315 | #define OPN_SLOT(N) ((N>>2)&3) |
||
316 | |||
317 | /* slot number */ |
||
318 | #define SLOT1 0 |
||
319 | #define SLOT2 2 |
||
320 | #define SLOT3 1 |
||
321 | #define SLOT4 3 |
||
322 | |||
323 | /* OPN key frequency number -> key code follow table */ |
||
324 | /* fnum higher 4bit -> keycode lower 2bit */ |
||
325 | static const UINT8 opn_fktable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3}; |
||
326 | |||
327 | static INT16/*signed int*/ tl_tab[TL_TAB_LEN]; |
||
328 | |||
329 | /* sin waveform table in 'decibel' scale */ |
||
330 | static UINT16/*unsigned int*/ sin_tab[SIN_LEN]; |
||
331 | |||
332 | /* current chip state */ |
||
333 | static void *_cur_chip = 0; /* pointer of current chip struct */ |
||
334 | static FM_ST *_State; /* basic status */ |
||
335 | static FM_CH *_cch[3]; /* pointer of FM channels */ |
||
336 | |||
337 | |||
338 | static INT32 _m2,_c1,_c2; /* Phase Modulation input for operators 2,3,4 */ |
||
339 | static INT32 _mem; /* one sample delay memory */ |
||
340 | |||
341 | static INT32 _out_fm[3]; /* outputs of working channels */ |
||
342 | |||
343 | /* limitter */ |
||
344 | |||
345 | #define Limit(val, max,min) { \ |
||
346 | if ( val > max ) val = max; \ |
||
347 | else if ( val < min ) val = min; \ |
||
348 | } |
||
349 | |||
350 | /* status set and IRQ handling */ |
||
351 | void FM_STATUS_SET(FM_ST *ST,int flag) |
||
352 | { |
||
353 | /* set status flag */ |
||
354 | ST->status |= flag; |
||
355 | if ( !(ST->irq) && (ST->status & ST->irqmask) ) |
||
356 | { |
||
357 | ST->irq = 1; |
||
358 | /* callback user interrupt handler (IRQ is OFF to ON) */ |
||
359 | // if(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->param,1); |
||
360 | } |
||
361 | } |
||
362 | |||
363 | /* status reset and IRQ handling */ |
||
364 | void FM_STATUS_RESET(FM_ST *ST,int flag) |
||
365 | { |
||
366 | /* reset status flag */ |
||
367 | ST->status &=~flag; |
||
368 | if ( (ST->irq) && !(ST->status & ST->irqmask) ) |
||
369 | { |
||
370 | ST->irq = 0; |
||
371 | /* callback user interrupt handler (IRQ is ON to OFF) */ |
||
372 | // if(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->param,0); |
||
373 | } |
||
374 | } |
||
375 | |||
376 | /* IRQ mask set */ |
||
377 | void FM_IRQMASK_SET(FM_ST *ST,int flag) |
||
378 | { |
||
379 | ST->irqmask = flag; |
||
380 | /* IRQ handling check */ |
||
381 | FM_STATUS_SET(ST,0); |
||
382 | FM_STATUS_RESET(ST,0); |
||
383 | } |
||
384 | |||
385 | |||
386 | /* OPN Mode Register Write */ |
||
387 | void set_timers( FM_ST *ST, void *n, int v ) |
||
388 | { |
||
389 | /* b7 = CSM MODE */ |
||
390 | /* b6 = 3 slot mode */ |
||
391 | /* b5 = reset b */ |
||
392 | /* b4 = reset a */ |
||
393 | /* b3 = timer enable b */ |
||
394 | /* b2 = timer enable a */ |
||
395 | /* b1 = load b */ |
||
396 | /* b0 = load a */ |
||
397 | ST->mode = v; |
||
398 | |||
399 | /* reset Timer b flag */ |
||
400 | if( v & 0x20 ) |
||
401 | FM_STATUS_RESET(ST,0x02); |
||
402 | /* reset Timer a flag */ |
||
403 | if( v & 0x10 ) |
||
404 | FM_STATUS_RESET(ST,0x01); |
||
405 | /* load b */ |
||
406 | if( v & 0x02 ) |
||
407 | { |
||
408 | if( ST->TBC == 0 ) |
||
409 | { |
||
410 | ST->TBC = ( 256-ST->TB)<<4; |
||
411 | /* External timer handler */ |
||
412 | // if (ST->Timer_Handler) (ST->Timer_Handler)(n,1,ST->TBC,ST->TimerBase); |
||
413 | } |
||
414 | } |
||
415 | else |
||
416 | { /* stop timer b */ |
||
417 | if( ST->TBC != 0 ) |
||
418 | { |
||
419 | ST->TBC = 0; |
||
420 | // if (ST->Timer_Handler) (ST->Timer_Handler)(n,1,0,ST->TimerBase); |
||
421 | } |
||
422 | } |
||
423 | /* load a */ |
||
424 | if( v & 0x01 ) |
||
425 | { |
||
426 | if( ST->TAC == 0 ) |
||
427 | { |
||
428 | ST->TAC = (1024-ST->TA); |
||
429 | /* External timer handler */ |
||
430 | // if (ST->Timer_Handler) (ST->Timer_Handler)(n,0,ST->TAC,ST->TimerBase); |
||
431 | } |
||
432 | } |
||
433 | else |
||
434 | { /* stop timer a */ |
||
435 | if( ST->TAC != 0 ) |
||
436 | { |
||
437 | ST->TAC = 0; |
||
438 | // if (ST->Timer_Handler) (ST->Timer_Handler)(n,0,0,ST->TimerBase); |
||
439 | } |
||
440 | } |
||
441 | } |
||
442 | |||
443 | /* Timer A Overflow */ |
||
444 | void TimerAOver(FM_ST *ST) |
||
445 | { |
||
446 | /* set status (if enabled) */ |
||
447 | if(ST->mode & 0x04) FM_STATUS_SET(ST,0x01); |
||
448 | /* clear or reload the counter */ |
||
449 | ST->TAC = (1024-ST->TA); |
||
450 | // if (ST->Timer_Handler) (ST->Timer_Handler)(ST->param,0,ST->TAC,ST->TimerBase); |
||
451 | } |
||
452 | /* Timer B Overflow */ |
||
453 | void TimerBOver(FM_ST *ST) |
||
454 | { |
||
455 | /* set status (if enabled) */ |
||
456 | if(ST->mode & 0x08) FM_STATUS_SET(ST,0x02); |
||
457 | /* clear or reload the counter */ |
||
458 | ST->TBC = ( 256-ST->TB)<<4; |
||
459 | // if (ST->Timer_Handler) (ST->Timer_Handler)(ST->param,1,ST->TBC,ST->TimerBase); |
||
460 | } |
||
461 | |||
462 | |||
463 | #if FM_BUSY_FLAG_SUPPORT |
||
464 | UINT8 FM_STATUS_FLAG(FM_ST *ST) |
||
465 | { |
||
466 | if( ST->BusyExpire ) |
||
467 | { |
||
468 | if( (ST->BusyExpire - FM_GET_TIME_NOW()) > 0) |
||
469 | return ST->status | 0x80; /* with busy */ |
||
470 | /* expire */ |
||
471 | ST->BusyExpire = 0; |
||
472 | } |
||
473 | return ST->status; |
||
474 | } |
||
475 | void FM_BUSY_SET(FM_ST *ST,int busyclock ) |
||
476 | { |
||
477 | ST->BusyExpire = FM_GET_TIME_NOW() + (ST->TimerBase * busyclock); |
||
478 | } |
||
479 | #define FM_BUSY_CLEAR(ST) ((ST)->BusyExpire = 0) |
||
480 | #else |
||
481 | #define FM_STATUS_FLAG(ST) ((ST)->status) |
||
482 | #define FM_BUSY_SET(ST,bclock) {} |
||
483 | #define FM_BUSY_CLEAR(ST) {} |
||
484 | #endif |
||
485 | |||
486 | |||
487 | void FM_KEYON(FM_CH *CH , int s ) |
||
488 | { |
||
489 | FM_SLOT *SLOT = &CH->SLOT[s]; |
||
490 | if( !SLOT->key ) |
||
491 | { |
||
492 | SLOT->key = 1; |
||
493 | SLOT->phase = 0; /* restart Phase Generator */ //restored by Alone Coder |
||
494 | SLOT->state = EG_ATT; /* phase -> Attack */ |
||
495 | if ( SLOT->volume >= MAX_ATT_INDEX )SLOT->volume = 511; /* Alone Coder */ |
||
496 | } |
||
497 | } |
||
498 | |||
499 | void FM_KEYOFF(FM_CH *CH , int s ) |
||
500 | { |
||
501 | FM_SLOT *SLOT = &CH->SLOT[s]; |
||
502 | if( SLOT->key ) |
||
503 | { |
||
504 | SLOT->key = 0; |
||
505 | if (SLOT->state>EG_REL) |
||
506 | SLOT->state = EG_REL;/* phase -> Release */ |
||
507 | } |
||
508 | } |
||
509 | |||
510 | /* set algorithm connection */ |
||
511 | static void setup_connection( FM_CH *CH, int ch ) |
||
512 | { |
||
513 | INT32 *carrier = &_out_fm[ch]; |
||
514 | |||
515 | INT32 **om1 = &CH->connect1; |
||
516 | INT32 **oc1 = &CH->connect2; |
||
517 | INT32 **om2 = &CH->connect3; |
||
518 | INT32 **memc = &CH->mem_connect; |
||
519 | |||
520 | switch( CH->ALGO ){ |
||
521 | case 0: |
||
522 | /* M1---C1---MEM---M2---C2---OUT */ |
||
523 | *om1 = &_c1; |
||
524 | *oc1 = &_mem; |
||
525 | *om2 = &_c2; |
||
526 | *memc= &_m2; |
||
527 | break; |
||
528 | case 1: |
||
529 | /* M1------+-MEM---M2---C2---OUT */ |
||
530 | /* C1-+ */ |
||
531 | *om1 = &_mem; |
||
532 | *oc1 = &_mem; |
||
533 | *om2 = &_c2; |
||
534 | *memc= &_m2; |
||
535 | break; |
||
536 | case 2: |
||
537 | /* M1-----------------+-C2---OUT */ |
||
538 | /* C1---MEM---M2-+ */ |
||
539 | *om1 = &_c2; |
||
540 | *oc1 = &_mem; |
||
541 | *om2 = &_c2; |
||
542 | *memc= &_m2; |
||
543 | break; |
||
544 | case 3: |
||
545 | /* M1---C1---MEM------+-C2---OUT */ |
||
546 | /* M2-+ */ |
||
547 | *om1 = &_c1; |
||
548 | *oc1 = &_mem; |
||
549 | *om2 = &_c2; |
||
550 | *memc= &_c2; |
||
551 | break; |
||
552 | case 4: |
||
553 | /* M1---C1-+-OUT */ |
||
554 | /* M2---C2-+ */ |
||
555 | /* MEM: not used */ |
||
556 | *om1 = &_c1; |
||
557 | *oc1 = carrier; |
||
558 | *om2 = &_c2; |
||
559 | *memc= &_mem; /* store it anywhere where it will not be used */ |
||
560 | break; |
||
561 | case 5: |
||
562 | /* +----C1----+ */ |
||
563 | /* M1-+-MEM---M2-+-OUT */ |
||
564 | /* +----C2----+ */ |
||
565 | *om1 = 0; /* special mark */ |
||
566 | *oc1 = carrier; |
||
567 | *om2 = carrier; |
||
568 | *memc= &_m2; |
||
569 | break; |
||
570 | case 6: |
||
571 | /* M1---C1-+ */ |
||
572 | /* M2-+-OUT */ |
||
573 | /* C2-+ */ |
||
574 | /* MEM: not used */ |
||
575 | *om1 = &_c1; |
||
576 | *oc1 = carrier; |
||
577 | *om2 = carrier; |
||
578 | *memc= &_mem; /* store it anywhere where it will not be used */ |
||
579 | break; |
||
580 | case 7: |
||
581 | /* M1-+ */ |
||
582 | /* C1-+-OUT */ |
||
583 | /* M2-+ */ |
||
584 | /* C2-+ */ |
||
585 | /* MEM: not used*/ |
||
586 | *om1 = carrier; |
||
587 | *oc1 = carrier; |
||
588 | *om2 = carrier; |
||
589 | *memc= &_mem; /* store it anywhere where it will not be used */ |
||
590 | break; |
||
591 | } |
||
592 | |||
593 | CH->connect4 = carrier; |
||
594 | } |
||
595 | |||
596 | /* set detune & multiple #3x */ |
||
597 | void set_det_mul(FM_ST *ST,FM_CH *CH,FM_SLOT *SLOT,int v) |
||
598 | { |
||
599 | SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1; |
||
600 | SLOT->DT = ST->dt_tab[(v>>4)&7]; |
||
601 | CH->SLOT[SLOT1].Incr=-1; |
||
602 | } |
||
603 | |||
604 | /* set total level #4x*/ |
||
605 | void set_tl(FM_CH *CH,FM_SLOT *SLOT , int v) |
||
606 | { |
||
607 | SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */ |
||
608 | } |
||
609 | |||
610 | /* set attack rate & key scale #5x */ |
||
611 | void set_ar_ksr(FM_CH *CH,FM_SLOT *SLOT,int v) |
||
612 | { |
||
613 | UINT8 old_KSR = SLOT->KSR; |
||
614 | |||
615 | SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; |
||
616 | |||
617 | SLOT->KSR = 3-(v>>6); |
||
618 | if (SLOT->KSR != old_KSR) |
||
619 | { |
||
620 | CH->SLOT[SLOT1].Incr=-1; |
||
621 | } |
||
622 | else |
||
623 | { |
||
624 | /* refresh Attack rate */ |
||
625 | if ((SLOT->ar + SLOT->ksr) < 32+62) |
||
626 | { |
||
627 | SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; |
||
628 | SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; |
||
629 | } |
||
630 | else |
||
631 | { |
||
632 | SLOT->eg_sh_ar = 0; |
||
633 | SLOT->eg_sel_ar = 17*RATE_STEPS; |
||
634 | } |
||
635 | } |
||
636 | } |
||
637 | |||
638 | /* set decay rate #6x*/ |
||
639 | void set_dr(FM_SLOT *SLOT,int v) |
||
640 | { |
||
641 | SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; |
||
642 | |||
643 | SLOT->eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr]; |
||
644 | SLOT->eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr]; |
||
645 | |||
646 | } |
||
647 | |||
648 | /* set sustain rate #7x*/ |
||
649 | void set_sr(FM_SLOT *SLOT,int v) |
||
650 | { |
||
651 | SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; |
||
652 | |||
653 | SLOT->eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr]; |
||
654 | SLOT->eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr]; |
||
655 | } |
||
656 | |||
657 | /* set release rate #8x*/ |
||
658 | void set_sl_rr(FM_SLOT *SLOT,int v) |
||
659 | { |
||
660 | SLOT->sl = sl_table[ v>>4 ]; |
||
661 | |||
662 | SLOT->rr = 34 + ((v&0x0f)<<2); |
||
663 | |||
664 | SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr]; |
||
665 | SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr]; |
||
666 | } |
||
667 | |||
668 | signed int op_calc(UINT32 phase, unsigned int env, signed int pm) |
||
669 | { |
||
670 | UINT32 p; |
||
671 | |||
672 | p = (env<<3) + sin_tab[ ( ((signed int)((phase & ~FREQ_MASK) + (pm<<15))) >> FREQ_SH ) & SIN_MASK ]; |
||
673 | |||
674 | if (p >= TL_TAB_LEN) |
||
675 | return 0; |
||
676 | return tl_tab[p]; |
||
677 | } |
||
678 | |||
679 | signed int op_calc1(UINT32 phase, unsigned int env, signed int pm) |
||
680 | { |
||
681 | UINT32 p; |
||
682 | |||
683 | p = (env<<3) + sin_tab[ ( ((signed int)((phase & ~FREQ_MASK) + pm )) >> FREQ_SH ) & SIN_MASK ]; |
||
684 | |||
685 | if (p >= TL_TAB_LEN) |
||
686 | return 0; |
||
687 | return tl_tab[p]; |
||
688 | } |
||
689 | |||
690 | |||
691 | void chan_calc(FM_OPN *OPN, FM_CH *CH) |
||
692 | { |
||
693 | unsigned int eg_out; |
||
694 | |||
695 | UINT32 AM = 0;//LFO_AM >> CH->ams; |
||
696 | |||
697 | _m2 = _c1 = _c2 = _mem = 0; |
||
698 | |||
699 | *CH->mem_connect = CH->mem_value; /* restore delayed sample (MEM) value to _m2 or _c2 */ |
||
700 | |||
701 | eg_out = CH->SLOT[SLOT1].vol_out; |
||
702 | { |
||
703 | INT32 out = CH->op1_out[0] + CH->op1_out[1]; |
||
704 | CH->op1_out[0] = CH->op1_out[1]; |
||
705 | |||
706 | if( !CH->connect1 ){ |
||
707 | /* algorithm 5 */ |
||
708 | _mem = _c1 = _c2 = CH->op1_out[0]; |
||
709 | }else{ |
||
710 | /* other algorithms */ |
||
711 | *CH->connect1 += CH->op1_out[0]; |
||
712 | } |
||
713 | |||
714 | CH->op1_out[1] = 0; |
||
715 | if( eg_out < ENV_QUIET ) /* SLOT 1 */ |
||
716 | { |
||
717 | if (!CH->FB) |
||
718 | out=0; |
||
719 | |||
720 | CH->op1_out[1] = op_calc1(CH->SLOT[SLOT1].phase, eg_out, (out<<CH->FB) ); |
||
721 | } |
||
722 | } |
||
723 | |||
724 | eg_out = CH->SLOT[SLOT3].vol_out; |
||
725 | if( eg_out < ENV_QUIET ) /* SLOT 3 */ |
||
726 | *CH->connect3 += op_calc(CH->SLOT[SLOT3].phase, eg_out, _m2); |
||
727 | |||
728 | eg_out = CH->SLOT[SLOT2].vol_out; |
||
729 | if( eg_out < ENV_QUIET ) /* SLOT 2 */ |
||
730 | *CH->connect2 += op_calc(CH->SLOT[SLOT2].phase, eg_out, _c1); |
||
731 | |||
732 | eg_out = CH->SLOT[SLOT4].vol_out; |
||
733 | if( eg_out < ENV_QUIET ) /* SLOT 4 */ |
||
734 | *CH->connect4 += op_calc(CH->SLOT[SLOT4].phase, eg_out, _c2); |
||
735 | |||
736 | |||
737 | /* store current MEM */ |
||
738 | CH->mem_value = _mem; |
||
739 | |||
740 | /* update phase counters AFTER output calculations */ |
||
741 | CH->SLOT[SLOT1].phase += CH->SLOT[SLOT1].Incr; |
||
742 | CH->SLOT[SLOT2].phase += CH->SLOT[SLOT2].Incr; |
||
743 | CH->SLOT[SLOT3].phase += CH->SLOT[SLOT3].Incr; |
||
744 | CH->SLOT[SLOT4].phase += CH->SLOT[SLOT4].Incr; |
||
745 | } |
||
746 | |||
747 | |||
748 | /* update phase increment and envelope generator */ |
||
749 | void refresh_fc_eg_slot(FM_SLOT *SLOT , int fc , int kc ) |
||
750 | { |
||
751 | int ksr; |
||
752 | |||
753 | /* (frequency) phase increment counter */ |
||
754 | SLOT->Incr = ((fc+SLOT->DT[kc])*SLOT->mul) >> 1; |
||
755 | |||
756 | ksr = kc >> SLOT->KSR; |
||
757 | if( SLOT->ksr != ksr ) |
||
758 | { |
||
759 | SLOT->ksr = ksr; |
||
760 | |||
761 | /* calculate envelope generator rates */ |
||
762 | if ((SLOT->ar + SLOT->ksr) < 32+62) |
||
763 | { |
||
764 | SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; |
||
765 | SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; |
||
766 | } |
||
767 | else |
||
768 | { |
||
769 | SLOT->eg_sh_ar = 0; |
||
770 | SLOT->eg_sel_ar = 17*RATE_STEPS; |
||
771 | } |
||
772 | |||
773 | SLOT->eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr]; |
||
774 | SLOT->eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr]; |
||
775 | |||
776 | SLOT->eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr]; |
||
777 | SLOT->eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr]; |
||
778 | |||
779 | SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr]; |
||
780 | SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr]; |
||
781 | } |
||
782 | } |
||
783 | |||
784 | /* update phase increment counters */ |
||
785 | void refresh_fc_eg_chan(FM_CH *CH ) |
||
786 | { |
||
787 | if( CH->SLOT[SLOT1].Incr==-1){ |
||
788 | int fc = CH->fc; |
||
789 | int kc = CH->kcode; |
||
790 | refresh_fc_eg_slot(&CH->SLOT[SLOT1] , fc , kc ); |
||
791 | refresh_fc_eg_slot(&CH->SLOT[SLOT2] , fc , kc ); |
||
792 | refresh_fc_eg_slot(&CH->SLOT[SLOT3] , fc , kc ); |
||
793 | refresh_fc_eg_slot(&CH->SLOT[SLOT4] , fc , kc ); |
||
794 | } |
||
795 | } |
||
796 | |||
797 | /* initialize time tables */ |
||
798 | static void init_timetables( FM_ST *ST , const UINT8 *dttable ) |
||
799 | { |
||
800 | int i,d; |
||
801 | double rate; |
||
802 | |||
803 | #if 0 |
||
804 | logerror("FM.C: samplerate=%8i chip clock=%8i freqbase=%f \n", |
||
805 | ST->rate, ST->clock, ST->freqbase ); |
||
806 | #endif |
||
807 | |||
808 | /* DeTune table */ |
||
809 | for (d = 0;d <= 3;d++){ |
||
810 | for (i = 0;i <= 31;i++){ |
||
811 | rate = ((double)dttable[d*32 + i]) * SIN_LEN * ST->freqbase * (1<<FREQ_SH) / ((double)(1<<20)); |
||
812 | ST->dt_tab[d][i] = (INT32) rate; |
||
813 | ST->dt_tab[d+4][i] = -(INT32) rate; |
||
814 | #if 0 |
||
815 | logerror("FM.C: DT [%2i %2i] = %8x \n", d, i, ST->dt_tab[d][i] ); |
||
816 | #endif |
||
817 | } |
||
818 | } |
||
819 | |||
820 | } |
||
821 | |||
822 | static void reset_channels( FM_ST *ST , FM_CH *CH , int num ) |
||
823 | { |
||
824 | int c,s; |
||
825 | |||
826 | ST->mode = 0; /* normal mode */ |
||
827 | ST->TA = 0; |
||
828 | ST->TAC = 0; |
||
829 | ST->TB = 0; |
||
830 | ST->TBC = 0; |
||
831 | |||
832 | for( c = 0 ; c < num ; c++ ) |
||
833 | { |
||
834 | CH[c].fc = 0; |
||
835 | for(s = 0 ; s < 4 ; s++ ) |
||
836 | { |
||
837 | CH[c].SLOT[s].ssg = 0; |
||
838 | CH[c].SLOT[s].ssgn = 0; |
||
839 | CH[c].SLOT[s].state= EG_OFF; |
||
840 | CH[c].SLOT[s].volume = MAX_ATT_INDEX; |
||
841 | CH[c].SLOT[s].vol_out= MAX_ATT_INDEX; |
||
842 | } |
||
843 | } |
||
844 | } |
||
845 | |||
846 | /* initialize generic tables */ |
||
847 | static int init_tables(void) |
||
848 | { |
||
849 | signed int i,x; |
||
850 | signed int n; |
||
851 | double o,m; |
||
852 | |||
853 | for (x=0; x<TL_RES_LEN; x++) |
||
854 | { |
||
855 | m = (1<<16) / pow((double)2, (double)((x+1) * (ENV_STEP/4.0) / 8.0)); |
||
856 | m = floor(m); |
||
857 | |||
858 | /* we never reach (1<<16) here due to the (x+1) */ |
||
859 | /* result fits within 16 bits at maximum */ |
||
860 | |||
861 | n = (int)m; /* 16 bits here */ |
||
862 | n >>= 4; /* 12 bits here */ |
||
863 | if (n&1) /* round to nearest */ |
||
864 | n = (n>>1)+1; |
||
865 | else |
||
866 | n = n>>1; |
||
867 | /* 11 bits here (rounded) */ |
||
868 | n <<= 2; /* 13 bits here (as in real chip) */ |
||
869 | tl_tab[ x*2 + 0 ] = n; |
||
870 | tl_tab[ x*2 + 1 ] = -n; |
||
871 | |||
872 | for (i=1; i<13; i++) |
||
873 | { |
||
874 | tl_tab[ x*2+0 + i*2*TL_RES_LEN ] = n>>i; |
||
875 | tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -(n>>i); |
||
876 | } |
||
877 | } |
||
878 | /*logerror("FM.C: TL_TAB_LEN = %i elements (%i bytes)\n",TL_TAB_LEN, (int)sizeof(tl_tab));*/ |
||
879 | |||
880 | |||
881 | for (i=0; i<SIN_LEN; i++) |
||
882 | { |
||
883 | /* non-standard sinus */ |
||
884 | m = sin( ((i*2)+1) * PI / SIN_LEN ); /* checked against the real chip */ |
||
885 | |||
886 | /* we never reach zero here due to ((i*2)+1) */ |
||
887 | if (m>0.0) |
||
888 | o = 8*(double)log(1.0/m)/log((double)2); /* convert to 'decibels' */ |
||
889 | else |
||
890 | o = 8*(double)log(-1.0/m)/log((double)2); /* convert to 'decibels' */ |
||
891 | |||
892 | o = o / (ENV_STEP/4); |
||
893 | |||
894 | n = (int)(2.0*o); |
||
895 | if (n&1) /* round to nearest */ |
||
896 | n = (n>>1)+1; |
||
897 | else |
||
898 | n = n>>1; |
||
899 | |||
900 | sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 ); |
||
901 | // printf("FM.C: sin [%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[i],tl_tab[sin_tab[i]]); |
||
902 | } |
||
903 | |||
904 | /*logerror("FM.C: ENV_QUIET= %08x\n",ENV_QUIET );*/ |
||
905 | |||
906 | return 1; |
||
907 | } |
||
908 | |||
909 | static void FMCloseTable( void ) |
||
910 | { |
||
911 | #ifdef SAVE_SAMPLE |
||
912 | // fclose(sample[0]); |
||
913 | #endif |
||
914 | return; |
||
915 | } |
||
916 | |||
917 | /* CSM Key Controll */ |
||
918 | void CSMKeyControll(FM_CH *CH) |
||
919 | { |
||
920 | /* this is wrong, atm */ |
||
921 | |||
922 | /* all key on */ |
||
923 | FM_KEYON(CH,SLOT1); |
||
924 | FM_KEYON(CH,SLOT2); |
||
925 | FM_KEYON(CH,SLOT3); |
||
926 | FM_KEYON(CH,SLOT4); |
||
927 | } |
||
928 | |||
929 | |||
930 | __inline void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT) |
||
931 | { |
||
932 | unsigned int out; |
||
933 | unsigned int swap_flag = 0; |
||
934 | unsigned int i; |
||
935 | |||
936 | |||
937 | i = 4; /* four operators per channel */ |
||
938 | do |
||
939 | { |
||
940 | switch(SLOT->state) |
||
941 | { |
||
942 | case EG_ATT: /* attack phase */ |
||
943 | if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_ar)-1) ) ) |
||
944 | { |
||
945 | SLOT->volume += (~SLOT->volume * |
||
946 | (eg_inc[SLOT->eg_sel_ar + ((OPN->eg_cnt>>SLOT->eg_sh_ar)&7)]) |
||
947 | ) >>4; |
||
948 | |||
949 | if (SLOT->volume <= MIN_ATT_INDEX) |
||
950 | { |
||
951 | SLOT->volume = MIN_ATT_INDEX; |
||
952 | SLOT->state = EG_DEC; |
||
953 | } |
||
954 | } |
||
955 | break; |
||
956 | |||
957 | case EG_DEC: /* decay phase */ |
||
958 | if (SLOT->ssg&0x08) /* SSG EG type envelope selected */ |
||
959 | { |
||
960 | if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d1r)-1) ) ) |
||
961 | { |
||
962 | SLOT->volume += 4 * eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)]; |
||
963 | |||
964 | if ( (UINT32)SLOT->volume >= SLOT->sl ) |
||
965 | SLOT->state = EG_SUS; |
||
966 | } |
||
967 | } |
||
968 | else |
||
969 | { |
||
970 | if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d1r)-1) ) ) |
||
971 | { |
||
972 | SLOT->volume += eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)]; |
||
973 | |||
974 | if ( (UINT32)SLOT->volume >= SLOT->sl ) |
||
975 | SLOT->state = EG_SUS; |
||
976 | } |
||
977 | } |
||
978 | break; |
||
979 | |||
980 | case EG_SUS: /* sustain phase */ |
||
981 | if (SLOT->ssg&0x08) /* SSG EG type envelope selected */ |
||
982 | { |
||
983 | if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d2r)-1) ) ) |
||
984 | { |
||
985 | SLOT->volume += 4 * eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)]; |
||
986 | |||
987 | if ( SLOT->volume >= 512 /* áûëî MAX_ATT_INDEX */ ) //Alone Coder |
||
988 | { |
||
989 | SLOT->volume = MAX_ATT_INDEX; |
||
990 | |||
991 | if (SLOT->ssg&0x01) /* bit 0 = hold */ |
||
992 | { |
||
993 | if (SLOT->ssgn&1) /* have we swapped once ??? */ |
||
994 | { |
||
995 | /* yes, so do nothing, just hold current level */ |
||
996 | } |
||
997 | else |
||
998 | swap_flag = (SLOT->ssg&0x02) | 1 ; /* bit 1 = alternate */ |
||
999 | |||
1000 | } |
||
1001 | else |
||
1002 | { |
||
1003 | /* same as KEY-ON operation */ |
||
1004 | |||
1005 | /* restart of the Phase Generator should be here, |
||
1006 | only if AR is not maximum ??? ALWAYS! */ |
||
1007 | SLOT->phase = 0; //Alone Coder |
||
1008 | |||
1009 | /* phase -> Attack */ |
||
1010 | SLOT->volume = 511; //Alone Coder |
||
1011 | SLOT->state = EG_ATT; |
||
1012 | |||
1013 | swap_flag = (SLOT->ssg&0x02); /* bit 1 = alternate */ |
||
1014 | } |
||
1015 | } |
||
1016 | } |
||
1017 | } |
||
1018 | else |
||
1019 | { |
||
1020 | if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d2r)-1) ) ) |
||
1021 | { |
||
1022 | SLOT->volume += eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)]; |
||
1023 | |||
1024 | if ( SLOT->volume >= MAX_ATT_INDEX ) |
||
1025 | { |
||
1026 | SLOT->volume = MAX_ATT_INDEX; |
||
1027 | /* do not change SLOT->state (verified on real chip) */ |
||
1028 | } |
||
1029 | } |
||
1030 | |||
1031 | } |
||
1032 | break; |
||
1033 | |||
1034 | case EG_REL: /* release phase */ |
||
1035 | if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_rr)-1) ) ) |
||
1036 | { |
||
1037 | SLOT->volume += eg_inc[SLOT->eg_sel_rr + ((OPN->eg_cnt>>SLOT->eg_sh_rr)&7)]; |
||
1038 | |||
1039 | if ( SLOT->volume >= MAX_ATT_INDEX ) |
||
1040 | { |
||
1041 | SLOT->volume = MAX_ATT_INDEX; |
||
1042 | SLOT->state = EG_OFF; |
||
1043 | } |
||
1044 | } |
||
1045 | break; |
||
1046 | |||
1047 | } |
||
1048 | |||
1049 | out = SLOT->tl + ((UINT32)SLOT->volume); |
||
1050 | |||
1051 | if ((SLOT->ssg&0x08) && (SLOT->ssgn&2) && (SLOT->state != EG_OFF/*Alone Coder*/)) /* negate output (changes come from alternate bit, init comes from attack bit) */ |
||
1052 | out ^= 511/*Alone Coder*/; //((1<<ENV_BITS)-1); /* 1023 */ |
||
1053 | |||
1054 | /* we need to store the result here because we are going to change ssgn |
||
1055 | in next instruction */ |
||
1056 | SLOT->vol_out = out; |
||
1057 | |||
1058 | SLOT->ssgn ^= swap_flag; |
||
1059 | |||
1060 | SLOT++; |
||
1061 | i--; |
||
1062 | }while (i); |
||
1063 | |||
1064 | } |
||
1065 | |||
1066 | enum { SS_INT8, SS_UINT8, SS_INT16, SS_UINT16, SS_INT32, SS_UINT32, SS_INT, SS_DOUBLE, SS_FLOAT}; |
||
1067 | |||
1068 | void ss_register_entry(const char *module, int instance, const char *name, int type, void *data, unsigned int size) |
||
1069 | { |
||
1070 | int i; |
||
1071 | FILE* logfile=fopen("logfile.log", "a+"); |
||
1072 | if(!logfile) |
||
1073 | return; |
||
1074 | |||
1075 | fprintf(logfile,"%20s:%3d [%10s]: ",module,instance,name); |
||
1076 | |||
1077 | if (type==SS_INT8) { fprintf(logfile,"INT8 "); for (i=0;i<(int)size;i++) fprintf(logfile,"[%2x]#%+02x ",i,((signed char*)data)[i]); } |
||
1078 | if (type==SS_INT16) { fprintf(logfile,"INT16 "); for (i=0;i<(int)size;i++) fprintf(logfile,"[%2x]#%+04x ",i,((signed short*)data)[i]); } |
||
1079 | if (type==SS_INT32) { fprintf(logfile,"INT32 "); for (i=0;i<(int)size;i++) fprintf(logfile,"[%2x]#%+08x ",i,((signed int*)data)[i]); } |
||
1080 | if (type==SS_UINT8&&size==256) { |
||
1081 | fprintf(logfile,"UINT8 "); |
||
1082 | for (i=0;i<(int)size;i++) { |
||
1083 | if (i%16==0) fprintf(logfile,"\n"); |
||
1084 | fprintf(logfile,"[%02x]#%02x ",i,((unsigned char*)data)[i]); |
||
1085 | } |
||
1086 | } |
||
1087 | else if (type==SS_UINT8) { fprintf(logfile,"UINT8 "); for (i=0;i<(int)size;i++) fprintf(logfile,"[%2x]#%02x ",i,((unsigned char*)data)[i]); } |
||
1088 | if (type==SS_UINT16) { fprintf(logfile,"UINT16 "); for (i=0;i<(int)size;i++) fprintf(logfile,"[%2x]#%04x ",i,((unsigned short*)data)[i]); } |
||
1089 | if (type==SS_UINT32) { fprintf(logfile,"UINT32 "); for (i=0;i<(int)size;i++) fprintf(logfile,"[%2x]#%08x ",i,((unsigned int*)data)[i]); } |
||
1090 | |||
1091 | if (type==SS_INT) { fprintf(logfile,"INT "); fprintf(logfile," %d ",((int*)data)[0]); } |
||
1092 | if (type==SS_DOUBLE) { fprintf(logfile,"DOUBLE "); for (i=0;i<(int)size;i++) fprintf(logfile,"[%d]%f ",i,((double*)data)[i]); } |
||
1093 | if (type==SS_FLOAT) { fprintf(logfile,"FLOAT "); for (i=0;i<(int)size;i++) fprintf(logfile,"[%d]%f ",i,((float*)data)[i]); } |
||
1094 | |||
1095 | fprintf(logfile,"\n"); |
||
1096 | |||
1097 | fclose(logfile); |
||
1098 | return; |
||
1099 | } |
||
1100 | |||
1101 | void state_save_register_UINT8 (const char *module, int instance, const char *name, UINT8 *val, unsigned size) |
||
1102 | { ss_register_entry(module, instance, name, SS_UINT8, val, size); } |
||
1103 | |||
1104 | void state_save_register_INT8 (const char *module, int instance, const char *name, INT8 *val, unsigned size) |
||
1105 | { ss_register_entry(module, instance, name, SS_INT8, val, size); } |
||
1106 | |||
1107 | void state_save_register_UINT16(const char *module, int instance, const char *name, UINT16 *val, unsigned size) |
||
1108 | { ss_register_entry(module, instance, name, SS_UINT16, val, size); } |
||
1109 | |||
1110 | void state_save_register_INT16 (const char *module, int instance, const char *name, INT16 *val, unsigned size) |
||
1111 | { ss_register_entry(module, instance, name, SS_INT16, val, size); } |
||
1112 | |||
1113 | void state_save_register_UINT32(const char *module, int instance, const char *name, UINT32 *val, unsigned size) |
||
1114 | { ss_register_entry(module, instance, name, SS_UINT32, val, size); } |
||
1115 | |||
1116 | void state_save_register_INT32 (const char *module, int instance, const char *name, INT32 *val, unsigned size) |
||
1117 | { ss_register_entry(module, instance, name, SS_INT32, val, size); } |
||
1118 | |||
1119 | void state_save_register_int (const char *module, int instance, const char *name, int *val) |
||
1120 | { ss_register_entry(module, instance, name, SS_INT, val, 1); } |
||
1121 | |||
1122 | void state_save_register_double(const char *module, int instance, const char *name, double *val, unsigned size) |
||
1123 | { ss_register_entry(module, instance, name, SS_DOUBLE, val, size); } |
||
1124 | |||
1125 | void state_save_register_float(const char *module, int instance, const char *name, float *val, unsigned size) |
||
1126 | { ss_register_entry(module, instance, name, SS_FLOAT, val, size); } |
||
1127 | |||
1128 | |||
1129 | /* FM channel save , internal state only */ |
||
1130 | static void FMsave_state_channel(const char *name,int num,FM_CH *CH,int num_ch) |
||
1131 | { |
||
1132 | int slot , ch; |
||
1133 | char state_name[20]; |
||
1134 | const char slot_array[4] = { 1 , 3 , 2 , 4 }; |
||
1135 | |||
1136 | for(ch=0;ch<num_ch;ch++,CH++) |
||
1137 | { |
||
1138 | /* channel */ |
||
1139 | sprintf(state_name,"%s.CH%d",name,ch); |
||
1140 | state_save_register_INT32(state_name, num, "feedback" , CH->op1_out , 2); |
||
1141 | state_save_register_UINT32(state_name, num, "phasestep" , &CH->fc , 1); |
||
1142 | state_save_register_UINT32(state_name, num, "block_fnum" , &CH->block_fnum , 1); |
||
1143 | /* slots */ |
||
1144 | for(slot=0;slot<4;slot++) |
||
1145 | { |
||
1146 | FM_SLOT *SLOT = &CH->SLOT[slot]; |
||
1147 | |||
1148 | sprintf(state_name,"%s.CH%d.SLOT%d",name,ch,slot_array[slot]); |
||
1149 | state_save_register_UINT32(state_name, num, "phasecount" , &SLOT->phase, 1); |
||
1150 | state_save_register_UINT8 (state_name, num, "state" , &SLOT->state, 1); |
||
1151 | state_save_register_INT32 (state_name, num, "volume" , &SLOT->volume, 1); |
||
1152 | } |
||
1153 | } |
||
1154 | } |
||
1155 | |||
1156 | static void FMsave_state_st(const char *state_name,int num,FM_ST *ST) |
||
1157 | { |
||
1158 | #if FM_BUSY_FLAG_SUPPORT |
||
1159 | state_save_register_double(state_name, num, "BusyExpire", &ST->BusyExpire , 1); |
||
1160 | #endif |
||
1161 | state_save_register_UINT8 (state_name, num, "address" , &ST->address , 1); |
||
1162 | state_save_register_UINT8 (state_name, num, "IRQ" , &ST->irq , 1); |
||
1163 | state_save_register_UINT8 (state_name, num, "IRQ MASK" , &ST->irqmask , 1); |
||
1164 | state_save_register_UINT8 (state_name, num, "status" , &ST->status , 1); |
||
1165 | state_save_register_UINT32(state_name, num, "mode" , &ST->mode , 1); |
||
1166 | state_save_register_UINT8 (state_name, num, "prescaler" , &ST->prescaler_sel , 1); |
||
1167 | state_save_register_UINT8 (state_name, num, "freq latch", &ST->fn_h , 1); |
||
1168 | state_save_register_int (state_name, num, "TIMER A" , &ST->TA ); |
||
1169 | state_save_register_int (state_name, num, "TIMER Acnt", &ST->TAC ); |
||
1170 | state_save_register_UINT8 (state_name, num, "TIMER B" , &ST->TB , 1); |
||
1171 | state_save_register_int (state_name, num, "TIMER Bcnt", &ST->TBC ); |
||
1172 | |||
1173 | state_save_register_int (state_name, num, "clock" , &ST->clock ); |
||
1174 | state_save_register_int (state_name, num, "rate" , &ST->rate ); |
||
1175 | } |
||
1176 | |||
1177 | |||
1178 | /* prescaler set (and make time tables) */ |
||
1179 | static void OPNSetPres(FM_OPN *OPN , int pres , int TimerPres, int SSGpres) |
||
1180 | { |
||
1181 | int i; |
||
1182 | |||
1183 | /* frequency base */ |
||
1184 | OPN->ST.freqbase = (OPN->ST.rate) ? ((double)OPN->ST.clock / OPN->ST.rate) / pres : 0; |
||
1185 | |||
1186 | #if 0 |
||
1187 | OPN->ST.rate = (double)OPN->ST.clock / pres; |
||
1188 | OPN->ST.freqbase = 1.0; |
||
1189 | #endif |
||
1190 | |||
1191 | OPN->eg_timer_add = (UINT32)((1<<EG_SH) * OPN->ST.freqbase); |
||
1192 | OPN->eg_timer_overflow = (UINT32)(( 3 ) * (1<<EG_SH)); |
||
1193 | |||
1194 | /* Timer base time */ |
||
1195 | OPN->ST.TimerBase = 1.0/((double)OPN->ST.clock / (double)TimerPres); |
||
1196 | |||
1197 | /* SSG part prescaler set */ |
||
1198 | // if( SSGpres ) (*OPN->ST.SSG->set_clock)( OPN->ST.param, OPN->ST.clock * 2 / SSGpres ); |
||
1199 | OPN->ST.SSGclock = OPN->ST.clock * 2 / SSGpres; |
||
1200 | |||
1201 | /* make time tables */ |
||
1202 | init_timetables( &OPN->ST, dt_tab ); |
||
1203 | |||
1204 | /* there are 2048 FNUMs that can be generated using FNUM/BLK registers*/ |
||
1205 | /* calculate fnumber -> increment counter table */ |
||
1206 | for(i = 0; i < 2048; i++) |
||
1207 | { |
||
1208 | /* freq table for octave 7 */ |
||
1209 | /* OPN phase increment counter = 20bit */ |
||
1210 | OPN->fn_table[i] = (UINT32)( (double)i * 64 * OPN->ST.freqbase * (1<<(FREQ_SH-10)) ); |
||
1211 | /* -10 because chip works with 10.10 fixed point, while we use 16.16 */ |
||
1212 | } |
||
1213 | |||
1214 | } |
||
1215 | |||
1216 | /* write a OPN mode register 0x20-0x2f */ |
||
1217 | static void OPNWriteMode(FM_OPN *OPN, int r, int v) |
||
1218 | { |
||
1219 | UINT8 c; |
||
1220 | FM_CH *CH; |
||
1221 | |||
1222 | switch(r){ |
||
1223 | case 0x21: /* Test */ |
||
1224 | break; |
||
1225 | case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */ |
||
1226 | break; |
||
1227 | case 0x24: /* timer A High 8*/ |
||
1228 | OPN->ST.TA = (OPN->ST.TA & 0x03)|(((int)v)<<2); |
||
1229 | break; |
||
1230 | case 0x25: /* timer A Low 2*/ |
||
1231 | OPN->ST.TA = (OPN->ST.TA & 0x3fc)|(v&3); |
||
1232 | break; |
||
1233 | case 0x26: /* timer B */ |
||
1234 | OPN->ST.TB = v; |
||
1235 | break; |
||
1236 | case 0x27: /* mode, timer control */ |
||
1237 | set_timers( &(OPN->ST),OPN->ST.param,v ); |
||
1238 | break; |
||
1239 | case 0x28: /* key on / off */ |
||
1240 | c = v & 0x03; |
||
1241 | if( c == 3 ) break; |
||
1242 | CH = OPN->P_CH; |
||
1243 | CH = &CH[c]; |
||
1244 | if(v&0x10) FM_KEYON(CH,SLOT1); else FM_KEYOFF(CH,SLOT1); |
||
1245 | if(v&0x20) FM_KEYON(CH,SLOT2); else FM_KEYOFF(CH,SLOT2); |
||
1246 | if(v&0x40) FM_KEYON(CH,SLOT3); else FM_KEYOFF(CH,SLOT3); |
||
1247 | if(v&0x80) FM_KEYON(CH,SLOT4); else FM_KEYOFF(CH,SLOT4); |
||
1248 | break; |
||
1249 | } |
||
1250 | } |
||
1251 | |||
1252 | /* write a OPN register (0x30-0xff) */ |
||
1253 | static void OPNWriteReg(FM_OPN *OPN, int r, int v) |
||
1254 | { |
||
1255 | FM_CH *CH; |
||
1256 | FM_SLOT *SLOT; |
||
1257 | |||
1258 | UINT8 c = OPN_CHAN(r); |
||
1259 | |||
1260 | if (c == 3) return; /* 0xX3,0xX7,0xXB,0xXF */ |
||
1261 | |||
1262 | CH = OPN->P_CH; |
||
1263 | CH = &CH[c]; |
||
1264 | |||
1265 | SLOT = &(CH->SLOT[OPN_SLOT(r)]); |
||
1266 | |||
1267 | switch( r & 0xf0 ) { |
||
1268 | case 0x30: /* DET , MUL */ |
||
1269 | set_det_mul(&OPN->ST,CH,SLOT,v); |
||
1270 | break; |
||
1271 | |||
1272 | case 0x40: /* TL */ |
||
1273 | set_tl(CH,SLOT,v); |
||
1274 | break; |
||
1275 | |||
1276 | case 0x50: /* KS, AR */ |
||
1277 | set_ar_ksr(CH,SLOT,v); |
||
1278 | break; |
||
1279 | |||
1280 | case 0x60: /* DR */ |
||
1281 | set_dr(SLOT,v); |
||
1282 | break; |
||
1283 | |||
1284 | case 0x70: /* SR */ |
||
1285 | set_sr(SLOT,v); |
||
1286 | break; |
||
1287 | |||
1288 | case 0x80: /* SL, RR */ |
||
1289 | set_sl_rr(SLOT,v); |
||
1290 | break; |
||
1291 | |||
1292 | case 0x90: /* SSG-EG */ |
||
1293 | |||
1294 | SLOT->ssg = v&0x0f; |
||
1295 | SLOT->ssgn = (v&0x04)>>1; /* bit 1 in ssgn = attack */ |
||
1296 | |||
1297 | /* SSG-EG envelope shapes : |
||
1298 | |||
1299 | E AtAlH |
||
1300 | 1 0 0 0 \\\\ |
||
1301 | |||
1302 | 1 0 0 1 \___ |
||
1303 | |||
1304 | 1 0 1 0 \/\/ |
||
1305 | ___ |
||
1306 | 1 0 1 1 \ |
||
1307 | |||
1308 | 1 1 0 0 //// |
||
1309 | ___ |
||
1310 | 1 1 0 1 / |
||
1311 | |||
1312 | 1 1 1 0 /\/\ |
||
1313 | |||
1314 | 1 1 1 1 /___ |
||
1315 | |||
1316 | |||
1317 | E = SSG-EG enable |
||
1318 | |||
1319 | The shapes are generated using Attack, Decay and Sustain phases. |
||
1320 | |||
1321 | Each single character in the diagrams above represents this whole |
||
1322 | sequence: |
||
1323 | |||
1324 | - when KEY-ON = 1, normal Attack phase is generated (*without* any |
||
1325 | difference when compared to normal mode), |
||
1326 | |||
1327 | - later, when envelope level reaches minimum level (max volume), |
||
1328 | the EG switches to Decay phase (which works with bigger steps |
||
1329 | when compared to normal mode - see below), |
||
1330 | |||
1331 | - later when envelope level passes the SL level, |
||
1332 | the EG switches to Sustain phase (which works with bigger steps |
||
1333 | when compared to normal mode - see below), |
||
1334 | |||
1335 | - finally when envelope level reaches maximum level (min volume), |
||
1336 | the EG switches to Attack phase again (depends on actual waveform). |
||
1337 | |||
1338 | Important is that when switch to Attack phase occurs, the phase counter |
||
1339 | of that operator will be zeroed-out (as in normal KEY-ON) but not always. |
||
1340 | (I havent found the rule for that - perhaps only when the output level is low) |
||
1341 | |||
1342 | The difference (when compared to normal Envelope Generator mode) is |
||
1343 | that the resolution in Decay and Sustain phases is 4 times lower; |
||
1344 | this results in only 256 steps instead of normal 1024. |
||
1345 | In other words: |
||
1346 | when SSG-EG is disabled, the step inside of the EG is one, |
||
1347 | when SSG-EG is enabled, the step is four (in Decay and Sustain phases). |
||
1348 | |||
1349 | Times between the level changes are the same in both modes. |
||
1350 | |||
1351 | |||
1352 | Important: |
||
1353 | Decay 1 Level (so called SL) is compared to actual SSG-EG output, so |
||
1354 | it is the same in both SSG and no-SSG modes, with this exception: |
||
1355 | |||
1356 | when the SSG-EG is enabled and is generating raising levels |
||
1357 | (when the EG output is inverted) the SL will be found at wrong level !!! |
||
1358 | For example, when SL=02: |
||
1359 | |||
1360 | 96-6 = -90dB in inverted EG output |
||
1361 | Which means that EG compares its level to SL as usual, and that the |
||
1362 | output is simply inverted afterall. |
||
1363 | |||
1364 | |||
1365 | The Yamaha's manuals say that AR should be set to 0x1f (max speed). |
||
1366 | That is not necessary, but then EG will be generating Attack phase. |
||
1367 | |||
1368 | */ |
||
1369 | |||
1370 | |||
1371 | break; |
||
1372 | |||
1373 | case 0xa0: |
||
1374 | switch( OPN_SLOT(r) ){ |
||
1375 | case 0: /* 0xa0-0xa2 : FNUM1 */ |
||
1376 | { |
||
1377 | UINT32 fn = (((UINT32)( (OPN->ST.fn_h)&7))<<8) + v; |
||
1378 | UINT8 blk = OPN->ST.fn_h>>3; |
||
1379 | /* keyscale code */ |
||
1380 | CH->kcode = (blk<<2) | opn_fktable[fn >> 7]; |
||
1381 | /* phase increment counter */ |
||
1382 | CH->fc = OPN->fn_table[fn]>>(7-blk); |
||
1383 | |||
1384 | /* store fnum in clear form for LFO PM calculations */ |
||
1385 | CH->block_fnum = (blk<<11) | fn; |
||
1386 | |||
1387 | CH->SLOT[SLOT1].Incr=-1; |
||
1388 | } |
||
1389 | break; |
||
1390 | case 1: /* 0xa4-0xa6 : FNUM2,BLK */ |
||
1391 | OPN->ST.fn_h = v&0x3f; |
||
1392 | break; |
||
1393 | case 2: /* 0xa8-0xaa : 3CH FNUM1 */ |
||
1394 | if(r < 0x100) |
||
1395 | { |
||
1396 | UINT32 fn = (((UINT32)(OPN->SL3.fn_h&7))<<8) + v; |
||
1397 | UINT8 blk = OPN->SL3.fn_h>>3; |
||
1398 | /* keyscale code */ |
||
1399 | OPN->SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7]; |
||
1400 | /* phase increment counter */ |
||
1401 | OPN->SL3.fc[c] = OPN->fn_table[fn]>>(7-blk); |
||
1402 | OPN->SL3.block_fnum[c] = fn; |
||
1403 | (OPN->P_CH)[2].SLOT[SLOT1].Incr=-1; |
||
1404 | } |
||
1405 | break; |
||
1406 | case 3: /* 0xac-0xae : 3CH FNUM2,BLK */ |
||
1407 | if(r < 0x100) |
||
1408 | OPN->SL3.fn_h = v&0x3f; |
||
1409 | break; |
||
1410 | } |
||
1411 | break; |
||
1412 | |||
1413 | case 0xb0: |
||
1414 | switch( OPN_SLOT(r) ){ |
||
1415 | case 0: /* 0xb0-0xb2 : FB,ALGO */ |
||
1416 | { |
||
1417 | int feedback = (v>>3)&7; |
||
1418 | CH->ALGO = v&7; |
||
1419 | CH->FB = feedback ? feedback+6 : 0; |
||
1420 | setup_connection( CH, c ); |
||
1421 | } |
||
1422 | break; |
||
1423 | } |
||
1424 | break; |
||
1425 | } |
||
1426 | } |
||
1427 | |||
1428 | |||
1429 | /* |
||
1430 | prescaler circuit (best guess to verified chip behaviour) |
||
1431 | |||
1432 | +--------------+ +-sel2-+ |
||
1433 | | +--|in20 | |
||
1434 | +---+ | +-sel1-+ | | |
||
1435 | M-CLK -+-|1/2|-+--|in10 | +---+ | out|--INT_CLOCK |
||
1436 | | +---+ | out|-|1/3|-|in21 | |
||
1437 | +----------|in11 | +---+ +------+ |
||
1438 | +------+ |
||
1439 | |||
1440 | reg.2d : sel2 = in21 (select sel2) |
||
1441 | reg.2e : sel1 = in11 (select sel1) |
||
1442 | reg.2f : sel1 = in10 , sel2 = in20 (clear selector) |
||
1443 | reset : sel1 = in11 , sel2 = in21 (clear both) |
||
1444 | |||
1445 | */ |
||
1446 | void OPNPrescaler_w(FM_OPN *OPN , int addr, int pre_divider) |
||
1447 | { |
||
1448 | static const int opn_pres[4] = { 2*12 , 2*12 , 6*12 , 3*12 }; |
||
1449 | static const int ssg_pres[4] = { 1 , 1 , 4 , 2 }; |
||
1450 | int sel; |
||
1451 | |||
1452 | switch(addr) |
||
1453 | { |
||
1454 | case 0: /* when reset */ |
||
1455 | OPN->ST.prescaler_sel = 2; |
||
1456 | break; |
||
1457 | case 1: /* when postload */ |
||
1458 | break; |
||
1459 | case 0x2d: /* divider sel : select 1/1 for 1/3line */ |
||
1460 | OPN->ST.prescaler_sel |= 0x02; |
||
1461 | break; |
||
1462 | case 0x2e: /* divider sel , select 1/3line for output */ |
||
1463 | OPN->ST.prescaler_sel |= 0x01; |
||
1464 | break; |
||
1465 | case 0x2f: /* divider sel , clear both selector to 1/2,1/2 */ |
||
1466 | OPN->ST.prescaler_sel = 0; |
||
1467 | break; |
||
1468 | } |
||
1469 | sel = OPN->ST.prescaler_sel & 3; |
||
1470 | /* update prescaler */ |
||
1471 | OPNSetPres( OPN, opn_pres[sel]*pre_divider, |
||
1472 | opn_pres[sel]*pre_divider, |
||
1473 | ssg_pres[sel]*pre_divider ); |
||
1474 | } |
||
1475 | |||
1476 | /*****************************************************************************/ |
||
1477 | /* YM2203 local section */ |
||
1478 | /*****************************************************************************/ |
||
1479 | |||
1480 | /* Generate samples for one of the YM2203s */ |
||
1481 | void YM2203UpdateOne(void *chip, FMSAMPLE *buffer, int length) |
||
1482 | { |
||
1483 | YM2203 *F2203 = (YM2203 *)chip; |
||
1484 | FM_OPN *OPN = &F2203->OPN; |
||
1485 | int i; |
||
1486 | FMSAMPLE *buf = buffer; |
||
1487 | |||
1488 | _cur_chip = (void *)F2203; |
||
1489 | _State = &F2203->OPN.ST; |
||
1490 | _cch[0] = &F2203->CH[0]; |
||
1491 | _cch[1] = &F2203->CH[1]; |
||
1492 | _cch[2] = &F2203->CH[2]; |
||
1493 | |||
1494 | /* refresh PG and EG */ |
||
1495 | refresh_fc_eg_chan( _cch[0] ); |
||
1496 | refresh_fc_eg_chan( _cch[1] ); |
||
1497 | if( ((_State->mode & 0xc0) == 0x40) ) |
||
1498 | { |
||
1499 | // 3SLOT MODE |
||
1500 | if( _cch[2]->SLOT[SLOT1].Incr==-1) |
||
1501 | { |
||
1502 | refresh_fc_eg_slot(&_cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] ); |
||
1503 | refresh_fc_eg_slot(&_cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] ); |
||
1504 | refresh_fc_eg_slot(&_cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] ); |
||
1505 | refresh_fc_eg_slot(&_cch[2]->SLOT[SLOT4] , _cch[2]->fc , _cch[2]->kcode ); |
||
1506 | } |
||
1507 | }else |
||
1508 | refresh_fc_eg_chan( _cch[2] ); |
||
1509 | |||
1510 | |||
1511 | /* buffering */ |
||
1512 | for (i=0; i < length ; i++) |
||
1513 | { |
||
1514 | /* clear outputs */ |
||
1515 | _out_fm[0] = 0; |
||
1516 | _out_fm[1] = 0; |
||
1517 | _out_fm[2] = 0; |
||
1518 | |||
1519 | /* advance envelope generator */ |
||
1520 | OPN->eg_timer += OPN->eg_timer_add; |
||
1521 | while (OPN->eg_timer >= OPN->eg_timer_overflow) |
||
1522 | { |
||
1523 | OPN->eg_timer -= OPN->eg_timer_overflow; |
||
1524 | OPN->eg_cnt++; |
||
1525 | |||
1526 | advance_eg_channel(OPN, &_cch[0]->SLOT[SLOT1]); |
||
1527 | advance_eg_channel(OPN, &_cch[1]->SLOT[SLOT1]); |
||
1528 | advance_eg_channel(OPN, &_cch[2]->SLOT[SLOT1]); |
||
1529 | } |
||
1530 | |||
1531 | /* calculate FM */ |
||
1532 | chan_calc(OPN, _cch[0] ); |
||
1533 | chan_calc(OPN, _cch[1] ); |
||
1534 | chan_calc(OPN, _cch[2] ); |
||
1535 | |||
1536 | /* buffering */ |
||
1537 | { |
||
1538 | int lt; |
||
1539 | lt = _out_fm[0] + _out_fm[1] + _out_fm[2]; |
||
1540 | lt >>= FINAL_SH; |
||
1541 | Limit( lt , MAXOUT, MINOUT ); |
||
1542 | // #ifdef SAVE_SAMPLE |
||
1543 | // SAVE_ALL_CHANNELS |
||
1544 | // #endif |
||
1545 | |||
1546 | /* buffering */ |
||
1547 | buf[i] = lt; |
||
1548 | } |
||
1549 | |||
1550 | /* timer A control */ |
||
1551 | INTERNAL_TIMER_A( _State , _cch[2] ) |
||
1552 | } |
||
1553 | INTERNAL_TIMER_B(_State,length) |
||
1554 | } |
||
1555 | |||
1556 | /* ---------- reset one of chip ---------- */ |
||
1557 | void YM2203ResetChip(void *chip) |
||
1558 | { |
||
1559 | int i; |
||
1560 | YM2203 *F2203 = (YM2203 *)chip; |
||
1561 | FM_OPN *OPN = &F2203->OPN; |
||
1562 | |||
1563 | /* Reset Prescaler */ |
||
1564 | OPNPrescaler_w(OPN, 0 , 1 ); |
||
1565 | /* reset SSG section */ |
||
1566 | // (*OPN->ST.SSG->reset)(OPN->ST.param); |
||
1567 | /* status clear */ |
||
1568 | FM_IRQMASK_SET(&OPN->ST,0x03); |
||
1569 | FM_BUSY_CLEAR(&OPN->ST); |
||
1570 | OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */ |
||
1571 | |||
1572 | OPN->eg_timer = 0; |
||
1573 | OPN->eg_cnt = 0; |
||
1574 | |||
1575 | FM_STATUS_RESET(&OPN->ST, 0xff); |
||
1576 | |||
1577 | reset_channels( &OPN->ST , F2203->CH , 3 ); |
||
1578 | /* reset OPerator paramater */ |
||
1579 | for(i = 0xb2 ; i >= 0x30 ; i-- ) OPNWriteReg(OPN,i,0); |
||
1580 | for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0); |
||
1581 | } |
||
1582 | |||
1583 | //#ifdef _STATE_H |
||
1584 | void YM2203Postload(void *chip) |
||
1585 | { |
||
1586 | if (chip) |
||
1587 | { |
||
1588 | YM2203 *F2203 = (YM2203 *)chip; |
||
1589 | int r; |
||
1590 | |||
1591 | /* prescaler */ |
||
1592 | OPNPrescaler_w(&F2203->OPN,1,1); |
||
1593 | |||
1594 | /* SSG registers */ |
||
1595 | for(r=0;r<16;r++) |
||
1596 | { |
||
1597 | // (*F2203->OPN.ST.SSG->write)(F2203->OPN.ST.param,0,r); |
||
1598 | // (*F2203->OPN.ST.SSG->write)(F2203->OPN.ST.param,1,F2203->REGS[r]); |
||
1599 | } |
||
1600 | |||
1601 | /* OPN registers */ |
||
1602 | /* DT / MULTI , TL , KS / AR , AMON / DR , SR , SL / RR , SSG-EG */ |
||
1603 | for(r=0x30;r<0x9e;r++) |
||
1604 | if((r&3) != 3) |
||
1605 | OPNWriteReg(&F2203->OPN,r,F2203->REGS[r]); |
||
1606 | /* FB / CONNECT , L / R / AMS / PMS */ |
||
1607 | for(r=0xb0;r<0xb6;r++) |
||
1608 | if((r&3) != 3) |
||
1609 | OPNWriteReg(&F2203->OPN,r,F2203->REGS[r]); |
||
1610 | |||
1611 | /* channels */ |
||
1612 | /*FM_channel_postload(F2203->CH,3);*/ |
||
1613 | } |
||
1614 | _cur_chip = NULL; |
||
1615 | } |
||
1616 | |||
1617 | void YM2203_save_state(void *chip, int index) |
||
1618 | { |
||
1619 | if (chip) |
||
1620 | { |
||
1621 | YM2203 *F2203 = (YM2203 *)chip; |
||
1622 | const char statename[] = "YM2203"; |
||
1623 | |||
1624 | state_save_register_UINT8 (statename, index, "regs" , F2203->REGS , 256); |
||
1625 | FMsave_state_st(statename,index,&F2203->OPN.ST); |
||
1626 | FMsave_state_channel(statename,index,F2203->CH,3); |
||
1627 | /* 3slots */ |
||
1628 | state_save_register_UINT32 (statename, index, "slot3fc" , F2203->OPN.SL3.fc , 3); |
||
1629 | state_save_register_UINT8 (statename, index, "slot3fh" , &F2203->OPN.SL3.fn_h , 1); |
||
1630 | state_save_register_UINT8 (statename, index, "slot3kc" , F2203->OPN.SL3.kcode , 3); |
||
1631 | } |
||
1632 | } |
||
1633 | //#endif /* _STATE_H */ |
||
1634 | |||
1635 | /* ---------- Initialize YM2203 emulator(s) ---------- |
||
1636 | 'num' is the number of virtual YM2203s to allocate |
||
1637 | 'clock' is the chip clock in Hz |
||
1638 | 'rate' is sampling rate |
||
1639 | */ |
||
1640 | void * YM2203Init(void *param, int index, int clock, int rate |
||
1641 | // ,FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler, |
||
1642 | // const struct ssg_callbacks *ssg |
||
1643 | ) |
||
1644 | { |
||
1645 | YM2203 *F2203; |
||
1646 | |||
1647 | _cur_chip = NULL; /* hiro-shi!! */ |
||
1648 | |||
1649 | /* allocate ym2203 state space */ |
||
1650 | if( (F2203 = (YM2203 *)malloc(sizeof(YM2203)))==NULL) |
||
1651 | return NULL; |
||
1652 | /* clear */ |
||
1653 | memset(F2203,0,sizeof(YM2203)); |
||
1654 | |||
1655 | if( !init_tables() ) |
||
1656 | { |
||
1657 | free( F2203 ); |
||
1658 | return NULL; |
||
1659 | } |
||
1660 | |||
1661 | F2203->OPN.ST.param = param; |
||
1662 | F2203->OPN.type = TYPE_YM2203; |
||
1663 | F2203->OPN.P_CH = F2203->CH; |
||
1664 | F2203->OPN.ST.clock = clock; |
||
1665 | F2203->OPN.ST.rate = rate; |
||
1666 | |||
1667 | // F2203->OPN.ST.Timer_Handler = TimerHandler; |
||
1668 | // F2203->OPN.ST.IRQ_Handler = IRQHandler; |
||
1669 | // F2203->OPN.ST.SSG = ssg; |
||
1670 | YM2203ResetChip(F2203); |
||
1671 | |||
1672 | #ifdef _STATE_H |
||
1673 | YM2203_save_state(F2203, index); |
||
1674 | #endif |
||
1675 | return F2203; |
||
1676 | } |
||
1677 | |||
1678 | /* shut down emulator */ |
||
1679 | void YM2203Shutdown(void *chip) |
||
1680 | { |
||
1681 | YM2203 *FM2203 = (YM2203 *)chip; |
||
1682 | |||
1683 | FMCloseTable(); |
||
1684 | free(FM2203); |
||
1685 | chip=NULL; |
||
1686 | } |
||
1687 | |||
1688 | /* YM2203 I/O interface */ |
||
1689 | int YM2203Write(void *chip,int a,UINT8 v) |
||
1690 | { |
||
1691 | YM2203 *F2203 = (YM2203 *)chip; |
||
1692 | FM_OPN *OPN = &F2203->OPN; |
||
1693 | |||
1694 | if( !(a&1) ) |
||
1695 | { // address port |
||
1696 | OPN->ST.address = (v &= 0xff); |
||
1697 | |||
1698 | // Write register to SSG emulator |
||
1699 | // if( v < 16 ) (*OPN->ST.SSG->write)(OPN->ST.param,0,v); |
||
1700 | |||
1701 | } |
||
1702 | else |
||
1703 | { // data port |
||
1704 | int addr = OPN->ST.address; |
||
1705 | // prescaler select : 2d,2e,2f |
||
1706 | if( addr >= 0x2d && addr <= 0x2f ) |
||
1707 | OPNPrescaler_w(OPN , addr , 1); |
||
1708 | else { |
||
1709 | //#ifdef _STATE_H |
||
1710 | F2203->REGS[addr] = v; |
||
1711 | //#endif |
||
1712 | switch( addr & 0xf0 ) |
||
1713 | { |
||
1714 | case 0x00: /* 0x00-0x0f : SSG section */ |
||
1715 | /* Write data to SSG emulator */ |
||
1716 | // (*OPN->ST.SSG->write)(OPN->ST.param,a,v); |
||
1717 | break; |
||
1718 | case 0x20: /* 0x20-0x2f : Mode section */ |
||
1719 | // YM2203UpdateReq(OPN->ST.param); |
||
1720 | /* write register */ |
||
1721 | OPNWriteMode(OPN,addr,v); |
||
1722 | break; |
||
1723 | default: /* 0x30-0xff : OPN section */ |
||
1724 | // YM2203UpdateReq(OPN->ST.param); |
||
1725 | /* write register */ |
||
1726 | OPNWriteReg(OPN,addr,v); |
||
1727 | } |
||
1728 | FM_BUSY_SET(&OPN->ST,1); |
||
1729 | } |
||
1730 | } |
||
1731 | return OPN->ST.irq; |
||
1732 | } |
||
1733 | |||
1734 | UINT8 YM2203Read(void *chip,int a) |
||
1735 | { |
||
1736 | YM2203 *F2203 = (YM2203 *)chip; |
||
1737 | int addr = F2203->OPN.ST.address; |
||
1738 | UINT8 ret = 0; |
||
1739 | |||
1740 | if( !(a&1) ) |
||
1741 | { /* status port */ |
||
1742 | ret = FM_STATUS_FLAG(&F2203->OPN.ST); |
||
1743 | } |
||
1744 | else |
||
1745 | { /* data port (only SSG) */ |
||
1746 | // if( addr < 16 ) ret = (*F2203->OPN.ST.SSG->read)(F2203->OPN.ST.param); |
||
1747 | } |
||
1748 | return ret; |
||
1749 | } |
||
1750 | |||
1751 | int YM2203TimerOver(void *chip,int c) |
||
1752 | { |
||
1753 | YM2203 *F2203 = (YM2203 *)chip; |
||
1754 | |||
1755 | if( c ) |
||
1756 | { /* Timer B */ |
||
1757 | TimerBOver( &(F2203->OPN.ST) ); |
||
1758 | } |
||
1759 | else |
||
1760 | { /* Timer A */ |
||
1761 | // YM2203UpdateReq(F2203->OPN.ST.param); |
||
1762 | /* timer update */ |
||
1763 | TimerAOver( &(F2203->OPN.ST) ); |
||
1764 | /* CSM mode key,TL control */ |
||
1765 | if( F2203->OPN.ST.mode & 0x80 ) |
||
1766 | { /* CSM mode auto key on */ |
||
1767 | CSMKeyControll( &(F2203->CH[2]) ); |
||
1768 | } |
||
1769 | } |
||
1770 | return F2203->OPN.ST.irq; |
||
1771 | } |