diff options
Diffstat (limited to 'apps/plugins/sdl/progs/wolf3d/fmopl_gpl.c')
-rw-r--r-- | apps/plugins/sdl/progs/wolf3d/fmopl_gpl.c | 2565 |
1 files changed, 2565 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/wolf3d/fmopl_gpl.c b/apps/plugins/sdl/progs/wolf3d/fmopl_gpl.c new file mode 100644 index 0000000000..41178d6bd9 --- /dev/null +++ b/apps/plugins/sdl/progs/wolf3d/fmopl_gpl.c | |||
@@ -0,0 +1,2565 @@ | |||
1 | /* | ||
2 | * Rockbox notes: | ||
3 | * | ||
4 | * This file is originally from the MAME project, from after their | ||
5 | * GPLv2 relicense. I (Franklin Wei) have made some modifications | ||
6 | * since then to make it work with the Wolf4SDL source. Notably, I | ||
7 | * corrected the behavior of YM3812Write() to write directly to the | ||
8 | * registers. Additionally, I fixed an unaligned write in OPL_CALC_CH | ||
9 | * which caused terrible output on ARM. | ||
10 | */ | ||
11 | |||
12 | // license:GPL-2.0+ | ||
13 | // copyright-holders:Jarek Burczynski,Tatsuyuki Satoh | ||
14 | /* | ||
15 | ** | ||
16 | ** File: fmopl.c - software implementation of FM sound generator | ||
17 | ** types OPL and OPL2 | ||
18 | ** | ||
19 | ** Copyright Jarek Burczynski (bujar at mame dot net) | ||
20 | ** Copyright Tatsuyuki Satoh , MultiArcadeMachineEmulator development | ||
21 | ** | ||
22 | ** Version 0.72 | ||
23 | ** | ||
24 | |||
25 | Revision History: | ||
26 | |||
27 | 04-08-2003 Jarek Burczynski: | ||
28 | - removed BFRDY hack. BFRDY is busy flag, and it should be 0 only when the chip | ||
29 | handles memory read/write or during the adpcm synthesis when the chip | ||
30 | requests another byte of ADPCM data. | ||
31 | |||
32 | 24-07-2003 Jarek Burczynski: | ||
33 | - added a small hack for Y8950 status BFRDY flag (bit 3 should be set after | ||
34 | some (unknown) delay). Right now it's always set. | ||
35 | |||
36 | 14-06-2003 Jarek Burczynski: | ||
37 | - implemented all of the status register flags in Y8950 emulation | ||
38 | - renamed y8950_set_delta_t_memory() parameters from _rom_ to _mem_ since | ||
39 | they can be either RAM or ROM | ||
40 | |||
41 | 08-10-2002 Jarek Burczynski (thanks to Dox for the YM3526 chip) | ||
42 | - corrected ym3526_read() to always set bit 2 and bit 1 | ||
43 | to HIGH state - identical to ym3812_read (verified on real YM3526) | ||
44 | |||
45 | 04-28-2002 Jarek Burczynski: | ||
46 | - binary exact Envelope Generator (verified on real YM3812); | ||
47 | compared to YM2151: the EG clock is equal to internal_clock, | ||
48 | rates are 2 times slower and volume resolution is one bit less | ||
49 | - modified interface functions (they no longer return pointer - | ||
50 | that's internal to the emulator now): | ||
51 | - new wrapper functions for OPLCreate: ym3526_init(), ym3812_init() and y8950_init() | ||
52 | - corrected 'off by one' error in feedback calculations (when feedback is off) | ||
53 | - enabled waveform usage (credit goes to Vlad Romascanu and zazzal22) | ||
54 | - speeded up noise generator calculations (Nicola Salmoria) | ||
55 | |||
56 | 03-24-2002 Jarek Burczynski (thanks to Dox for the YM3812 chip) | ||
57 | Complete rewrite (all verified on real YM3812): | ||
58 | - corrected sin_tab and tl_tab data | ||
59 | - corrected operator output calculations | ||
60 | - corrected waveform_select_enable register; | ||
61 | simply: ignore all writes to waveform_select register when | ||
62 | waveform_select_enable == 0 and do not change the waveform previously selected. | ||
63 | - corrected KSR handling | ||
64 | - corrected Envelope Generator: attack shape, Sustain mode and | ||
65 | Percussive/Non-percussive modes handling | ||
66 | - Envelope Generator rates are two times slower now | ||
67 | - LFO amplitude (tremolo) and phase modulation (vibrato) | ||
68 | - rhythm sounds phase generation | ||
69 | - white noise generator (big thanks to Olivier Galibert for mentioning Berlekamp-Massey algorithm) | ||
70 | - corrected key on/off handling (the 'key' signal is ORed from three sources: FM, rhythm and CSM) | ||
71 | - funky details (like ignoring output of operator 1 in BD rhythm sound when connect == 1) | ||
72 | |||
73 | 12-28-2001 Acho A. Tang | ||
74 | - reflected Delta-T EOS status on Y8950 status port. | ||
75 | - fixed subscription range of attack/decay tables | ||
76 | |||
77 | |||
78 | To do: | ||
79 | add delay before key off in CSM mode (see CSMKeyControll) | ||
80 | verify volume of the FM part on the Y8950 | ||
81 | */ | ||
82 | |||
83 | #include "fmopl.h" | ||
84 | |||
85 | |||
86 | |||
87 | /* output final shift */ | ||
88 | #if (OPL_SAMPLE_BITS==16) | ||
89 | #define FINAL_SH (0) | ||
90 | #define MAXOUT (+32767) | ||
91 | #define MINOUT (-32768) | ||
92 | #else | ||
93 | #define FINAL_SH (8) | ||
94 | #define MAXOUT (+127) | ||
95 | #define MINOUT (-128) | ||
96 | #endif | ||
97 | |||
98 | |||
99 | #define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */ | ||
100 | #define EG_SH 16 /* 16.16 fixed point (EG timing) */ | ||
101 | #define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */ | ||
102 | #define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */ | ||
103 | |||
104 | #define FREQ_MASK ((1<<FREQ_SH)-1) | ||
105 | |||
106 | /* envelope output entries */ | ||
107 | #define ENV_BITS 10 | ||
108 | #define ENV_LEN (1<<ENV_BITS) | ||
109 | #define ENV_STEP (128.0/ENV_LEN) | ||
110 | |||
111 | #define MAX_ATT_INDEX ((1<<(ENV_BITS-1))-1) /*511*/ | ||
112 | #define MIN_ATT_INDEX (0) | ||
113 | |||
114 | /* sinwave entries */ | ||
115 | #define SIN_BITS 10 | ||
116 | #define SIN_LEN (1<<SIN_BITS) | ||
117 | #define SIN_MASK (SIN_LEN-1) | ||
118 | |||
119 | #define TL_RES_LEN (256) /* 8 bits addressing (real chip) */ | ||
120 | |||
121 | |||
122 | |||
123 | /* register number to channel number , slot offset */ | ||
124 | #define SLOT1 0 | ||
125 | #define SLOT2 1 | ||
126 | |||
127 | /* Envelope Generator phases */ | ||
128 | |||
129 | #define EG_ATT 4 | ||
130 | #define EG_DEC 3 | ||
131 | #define EG_SUS 2 | ||
132 | #define EG_REL 1 | ||
133 | #define EG_OFF 0 | ||
134 | |||
135 | |||
136 | /* save output as raw 16-bit sample */ | ||
137 | |||
138 | /*#define SAVE_SAMPLE*/ | ||
139 | |||
140 | #ifdef SAVE_SAMPLE | ||
141 | static signed int acc_calc(signed int value) | ||
142 | { | ||
143 | if (value>=0) | ||
144 | { | ||
145 | if (value < 0x0200) | ||
146 | return (value & ~0); | ||
147 | if (value < 0x0400) | ||
148 | return (value & ~1); | ||
149 | if (value < 0x0800) | ||
150 | return (value & ~3); | ||
151 | if (value < 0x1000) | ||
152 | return (value & ~7); | ||
153 | if (value < 0x2000) | ||
154 | return (value & ~15); | ||
155 | if (value < 0x4000) | ||
156 | return (value & ~31); | ||
157 | return (value & ~63); | ||
158 | } | ||
159 | /*else value < 0*/ | ||
160 | if (value > -0x0200) | ||
161 | return (~abs(value) & ~0); | ||
162 | if (value > -0x0400) | ||
163 | return (~abs(value) & ~1); | ||
164 | if (value > -0x0800) | ||
165 | return (~abs(value) & ~3); | ||
166 | if (value > -0x1000) | ||
167 | return (~abs(value) & ~7); | ||
168 | if (value > -0x2000) | ||
169 | return (~abs(value) & ~15); | ||
170 | if (value > -0x4000) | ||
171 | return (~abs(value) & ~31); | ||
172 | return (~abs(value) & ~63); | ||
173 | } | ||
174 | |||
175 | |||
176 | static FILE *sample[1]; | ||
177 | #if 1 /*save to MONO file */ | ||
178 | #define SAVE_ALL_CHANNELS \ | ||
179 | { signed int pom = acc_calc(lt); \ | ||
180 | fputc((unsigned short)pom&0xff,sample[0]); \ | ||
181 | fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ | ||
182 | } | ||
183 | #else /*save to STEREO file */ | ||
184 | #define SAVE_ALL_CHANNELS \ | ||
185 | { signed int pom = lt; \ | ||
186 | fputc((unsigned short)pom&0xff,sample[0]); \ | ||
187 | fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ | ||
188 | pom = rt; \ | ||
189 | fputc((unsigned short)pom&0xff,sample[0]); \ | ||
190 | fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ | ||
191 | } | ||
192 | #endif | ||
193 | #endif | ||
194 | |||
195 | #define LOG_CYM_FILE 0 | ||
196 | static FILE * cymfile = NULL; | ||
197 | |||
198 | |||
199 | |||
200 | #define OPL_TYPE_WAVESEL 0x01 /* waveform select */ | ||
201 | #define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */ | ||
202 | #define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */ | ||
203 | #define OPL_TYPE_IO 0x08 /* I/O port */ | ||
204 | |||
205 | /* ---------- Generic interface section ---------- */ | ||
206 | #define OPL_TYPE_YM3526 (0) | ||
207 | #define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL) | ||
208 | #define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO) | ||
209 | |||
210 | |||
211 | |||
212 | struct OPL_SLOT | ||
213 | { | ||
214 | UINT32 ar; /* attack rate: AR<<2 */ | ||
215 | UINT32 dr; /* decay rate: DR<<2 */ | ||
216 | UINT32 rr; /* release rate:RR<<2 */ | ||
217 | UINT8 KSR; /* key scale rate */ | ||
218 | UINT8 ksl; /* keyscale level */ | ||
219 | UINT8 ksr; /* key scale rate: kcode>>KSR */ | ||
220 | UINT8 mul; /* multiple: mul_tab[ML] */ | ||
221 | |||
222 | /* Phase Generator */ | ||
223 | UINT32 Cnt; /* frequency counter */ | ||
224 | UINT32 Incr; /* frequency counter step */ | ||
225 | UINT8 FB; /* feedback shift value */ | ||
226 | INT32 *connect1; /* slot1 output pointer */ | ||
227 | INT32 op1_out[2]; /* slot1 output for feedback */ | ||
228 | UINT8 CON; /* connection (algorithm) type */ | ||
229 | |||
230 | /* Envelope Generator */ | ||
231 | UINT8 eg_type; /* percussive/non-percussive mode */ | ||
232 | UINT8 state; /* phase type */ | ||
233 | UINT32 TL; /* total level: TL << 2 */ | ||
234 | INT32 TLL; /* adjusted now TL */ | ||
235 | INT32 volume; /* envelope counter */ | ||
236 | UINT32 sl; /* sustain level: sl_tab[SL] */ | ||
237 | UINT8 eg_sh_ar; /* (attack state) */ | ||
238 | UINT8 eg_sel_ar; /* (attack state) */ | ||
239 | UINT8 eg_sh_dr; /* (decay state) */ | ||
240 | UINT8 eg_sel_dr; /* (decay state) */ | ||
241 | UINT8 eg_sh_rr; /* (release state) */ | ||
242 | UINT8 eg_sel_rr; /* (release state) */ | ||
243 | UINT32 key; /* 0 = KEY OFF, >0 = KEY ON */ | ||
244 | |||
245 | /* LFO */ | ||
246 | UINT32 AMmask; /* LFO Amplitude Modulation enable mask */ | ||
247 | UINT8 vib; /* LFO Phase Modulation enable flag (active high)*/ | ||
248 | |||
249 | /* waveform select */ | ||
250 | UINT16 wavetable; | ||
251 | }; | ||
252 | |||
253 | typedef struct OPL_SLOT OPL_SLOT; | ||
254 | |||
255 | struct OPL_CH | ||
256 | { | ||
257 | OPL_SLOT SLOT[2]; | ||
258 | /* phase generator state */ | ||
259 | UINT32 block_fnum; /* block+fnum */ | ||
260 | UINT32 fc; /* Freq. Increment base */ | ||
261 | UINT32 ksl_base; /* KeyScaleLevel Base step */ | ||
262 | UINT8 kcode; /* key code (for key scaling) */ | ||
263 | }; | ||
264 | |||
265 | typedef struct OPL_CH OPL_CH; | ||
266 | |||
267 | /* OPL state */ | ||
268 | struct FM_OPL | ||
269 | { | ||
270 | // moved to beginning to fix alignment | ||
271 | signed int phase_modulation __attribute__((aligned)); /* phase modulation input (SLOT 2) */ | ||
272 | signed int output[1] __attribute__((aligned)); | ||
273 | |||
274 | /* FM channel slots */ | ||
275 | OPL_CH P_CH[9]; /* OPL/OPL2 chips have 9 channels*/ | ||
276 | |||
277 | UINT32 eg_cnt; /* global envelope generator counter */ | ||
278 | UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/72 */ | ||
279 | UINT32 eg_timer_add; /* step of eg_timer */ | ||
280 | UINT32 eg_timer_overflow; /* envelope generator timer overlfows every 1 sample (on real chip) */ | ||
281 | |||
282 | UINT8 rhythm; /* Rhythm mode */ | ||
283 | |||
284 | UINT32 fn_tab[1024]; /* fnumber->increment counter */ | ||
285 | |||
286 | /* LFO */ | ||
287 | UINT32 LFO_AM; | ||
288 | INT32 LFO_PM; | ||
289 | |||
290 | UINT8 lfo_am_depth; | ||
291 | UINT8 lfo_pm_depth_range; | ||
292 | UINT32 lfo_am_cnt; | ||
293 | UINT32 lfo_am_inc; | ||
294 | UINT32 lfo_pm_cnt; | ||
295 | UINT32 lfo_pm_inc; | ||
296 | |||
297 | UINT32 noise_rng; /* 23 bit noise shift register */ | ||
298 | UINT32 noise_p; /* current noise 'phase' */ | ||
299 | UINT32 noise_f; /* current noise period */ | ||
300 | |||
301 | UINT8 wavesel; /* waveform select enable flag */ | ||
302 | |||
303 | UINT32 T[2]; /* timer counters */ | ||
304 | UINT8 st[2]; /* timer enable */ | ||
305 | |||
306 | #if BUILD_Y8950 | ||
307 | /* Delta-T ADPCM unit (Y8950) */ | ||
308 | |||
309 | YM_DELTAT *deltat; | ||
310 | |||
311 | /* Keyboard and I/O ports interface */ | ||
312 | UINT8 portDirection; | ||
313 | UINT8 portLatch; | ||
314 | OPL_PORTHANDLER_R porthandler_r; | ||
315 | OPL_PORTHANDLER_W porthandler_w; | ||
316 | void * port_param; | ||
317 | OPL_PORTHANDLER_R keyboardhandler_r; | ||
318 | OPL_PORTHANDLER_W keyboardhandler_w; | ||
319 | void * keyboard_param; | ||
320 | #endif | ||
321 | |||
322 | /* external event callback handlers */ | ||
323 | OPL_TIMERHANDLER timer_handler; /* TIMER handler */ | ||
324 | void *TimerParam; /* TIMER parameter */ | ||
325 | OPL_IRQHANDLER IRQHandler; /* IRQ handler */ | ||
326 | void *IRQParam; /* IRQ parameter */ | ||
327 | OPL_UPDATEHANDLER UpdateHandler;/* stream update handler */ | ||
328 | void *UpdateParam; /* stream update parameter */ | ||
329 | |||
330 | UINT8 type; /* chip type */ | ||
331 | UINT8 address; /* address register */ | ||
332 | UINT8 status; /* status flag */ | ||
333 | UINT8 statusmask; /* status mask */ | ||
334 | UINT8 mode; /* Reg.08 : CSM,notesel,etc. */ | ||
335 | |||
336 | UINT32 clock; /* master clock (Hz) */ | ||
337 | UINT32 rate; /* sampling rate (Hz) */ | ||
338 | double freqbase; /* frequency base */ | ||
339 | double TimerBase; /* Timer base time (==sampling time)*/ | ||
340 | device_t *device; | ||
341 | |||
342 | #if BUILD_Y8950 | ||
343 | INT32 output_deltat[4]; /* for Y8950 DELTA-T, chip is mono, that 4 here is just for safety */ | ||
344 | #endif | ||
345 | } __attribute__((aligned)); | ||
346 | |||
347 | typedef struct FM_OPL FM_OPL; | ||
348 | |||
349 | /* mapping of register number (offset) to slot number used by the emulator */ | ||
350 | static const int slot_array[32]= | ||
351 | { | ||
352 | 0, 2, 4, 1, 3, 5,-1,-1, | ||
353 | 6, 8,10, 7, 9,11,-1,-1, | ||
354 | 12,14,16,13,15,17,-1,-1, | ||
355 | -1,-1,-1,-1,-1,-1,-1,-1 | ||
356 | }; | ||
357 | |||
358 | /* key scale level */ | ||
359 | /* table is 3dB/octave , DV converts this into 6dB/octave */ | ||
360 | /* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */ | ||
361 | #define DV (0.1875/2.0) | ||
362 | static const UINT32 ksl_tab[8*16]= | ||
363 | { | ||
364 | /* OCT 0 */ | ||
365 | 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, | ||
366 | 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, | ||
367 | 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, | ||
368 | 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, | ||
369 | /* OCT 1 */ | ||
370 | 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, | ||
371 | 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, | ||
372 | 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV, | ||
373 | 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV, | ||
374 | /* OCT 2 */ | ||
375 | 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, | ||
376 | 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV, | ||
377 | 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV, | ||
378 | 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV, | ||
379 | /* OCT 3 */ | ||
380 | 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV, | ||
381 | 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV, | ||
382 | 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV, | ||
383 | 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV, | ||
384 | /* OCT 4 */ | ||
385 | 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV, | ||
386 | 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV, | ||
387 | 9.000/DV, 9.750/DV,10.125/DV,10.500/DV, | ||
388 | 10.875/DV,11.250/DV,11.625/DV,12.000/DV, | ||
389 | /* OCT 5 */ | ||
390 | 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV, | ||
391 | 9.000/DV,10.125/DV,10.875/DV,11.625/DV, | ||
392 | 12.000/DV,12.750/DV,13.125/DV,13.500/DV, | ||
393 | 13.875/DV,14.250/DV,14.625/DV,15.000/DV, | ||
394 | /* OCT 6 */ | ||
395 | 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV, | ||
396 | 12.000/DV,13.125/DV,13.875/DV,14.625/DV, | ||
397 | 15.000/DV,15.750/DV,16.125/DV,16.500/DV, | ||
398 | 16.875/DV,17.250/DV,17.625/DV,18.000/DV, | ||
399 | /* OCT 7 */ | ||
400 | 0.000/DV, 9.000/DV,12.000/DV,13.875/DV, | ||
401 | 15.000/DV,16.125/DV,16.875/DV,17.625/DV, | ||
402 | 18.000/DV,18.750/DV,19.125/DV,19.500/DV, | ||
403 | 19.875/DV,20.250/DV,20.625/DV,21.000/DV | ||
404 | }; | ||
405 | #undef DV | ||
406 | |||
407 | /* 0 / 3.0 / 1.5 / 6.0 dB/OCT */ | ||
408 | static const UINT32 ksl_shift[4] = { 31, 1, 2, 0 }; | ||
409 | |||
410 | |||
411 | /* sustain level table (3dB per step) */ | ||
412 | /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/ | ||
413 | #define SC(db) (UINT32) ( db * (2.0/ENV_STEP) ) | ||
414 | static const UINT32 sl_tab[16]={ | ||
415 | SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7), | ||
416 | SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31) | ||
417 | }; | ||
418 | #undef SC | ||
419 | |||
420 | |||
421 | #define RATE_STEPS (8) | ||
422 | static const unsigned char eg_inc[15*RATE_STEPS]={ | ||
423 | /*cycle:0 1 2 3 4 5 6 7*/ | ||
424 | |||
425 | /* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */ | ||
426 | /* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */ | ||
427 | /* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */ | ||
428 | /* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */ | ||
429 | |||
430 | /* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */ | ||
431 | /* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */ | ||
432 | /* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */ | ||
433 | /* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */ | ||
434 | |||
435 | /* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */ | ||
436 | /* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */ | ||
437 | /*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */ | ||
438 | /*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */ | ||
439 | |||
440 | /*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 4) */ | ||
441 | /*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 2, 15 3 for attack */ | ||
442 | /*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */ | ||
443 | }; | ||
444 | |||
445 | |||
446 | #define O(a) (a*RATE_STEPS) | ||
447 | |||
448 | /*note that there is no O(13) in this table - it's directly in the code */ | ||
449 | static const unsigned char eg_rate_select[16+64+16]={ /* Envelope Generator rates (16 + 64 rates + 16 RKS) */ | ||
450 | /* 16 infinite time rates */ | ||
451 | O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14), | ||
452 | O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14), | ||
453 | |||
454 | /* rates 00-12 */ | ||
455 | O( 0),O( 1),O( 2),O( 3), | ||
456 | O( 0),O( 1),O( 2),O( 3), | ||
457 | O( 0),O( 1),O( 2),O( 3), | ||
458 | O( 0),O( 1),O( 2),O( 3), | ||
459 | O( 0),O( 1),O( 2),O( 3), | ||
460 | O( 0),O( 1),O( 2),O( 3), | ||
461 | O( 0),O( 1),O( 2),O( 3), | ||
462 | O( 0),O( 1),O( 2),O( 3), | ||
463 | O( 0),O( 1),O( 2),O( 3), | ||
464 | O( 0),O( 1),O( 2),O( 3), | ||
465 | O( 0),O( 1),O( 2),O( 3), | ||
466 | O( 0),O( 1),O( 2),O( 3), | ||
467 | O( 0),O( 1),O( 2),O( 3), | ||
468 | |||
469 | /* rate 13 */ | ||
470 | O( 4),O( 5),O( 6),O( 7), | ||
471 | |||
472 | /* rate 14 */ | ||
473 | O( 8),O( 9),O(10),O(11), | ||
474 | |||
475 | /* rate 15 */ | ||
476 | O(12),O(12),O(12),O(12), | ||
477 | |||
478 | /* 16 dummy rates (same as 15 3) */ | ||
479 | O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12), | ||
480 | O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12), | ||
481 | |||
482 | }; | ||
483 | #undef O | ||
484 | |||
485 | /*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 */ | ||
486 | /*shift 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 */ | ||
487 | /*mask 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0 */ | ||
488 | |||
489 | #define O(a) (a*1) | ||
490 | static const unsigned char eg_rate_shift[16+64+16]={ /* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */ | ||
491 | /* 16 infinite time rates */ | ||
492 | O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), | ||
493 | O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), | ||
494 | |||
495 | /* rates 00-12 */ | ||
496 | O(12),O(12),O(12),O(12), | ||
497 | O(11),O(11),O(11),O(11), | ||
498 | O(10),O(10),O(10),O(10), | ||
499 | O( 9),O( 9),O( 9),O( 9), | ||
500 | O( 8),O( 8),O( 8),O( 8), | ||
501 | O( 7),O( 7),O( 7),O( 7), | ||
502 | O( 6),O( 6),O( 6),O( 6), | ||
503 | O( 5),O( 5),O( 5),O( 5), | ||
504 | O( 4),O( 4),O( 4),O( 4), | ||
505 | O( 3),O( 3),O( 3),O( 3), | ||
506 | O( 2),O( 2),O( 2),O( 2), | ||
507 | O( 1),O( 1),O( 1),O( 1), | ||
508 | O( 0),O( 0),O( 0),O( 0), | ||
509 | |||
510 | /* rate 13 */ | ||
511 | O( 0),O( 0),O( 0),O( 0), | ||
512 | |||
513 | /* rate 14 */ | ||
514 | O( 0),O( 0),O( 0),O( 0), | ||
515 | |||
516 | /* rate 15 */ | ||
517 | O( 0),O( 0),O( 0),O( 0), | ||
518 | |||
519 | /* 16 dummy rates (same as 15 3) */ | ||
520 | O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), | ||
521 | O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), | ||
522 | |||
523 | }; | ||
524 | #undef O | ||
525 | |||
526 | |||
527 | /* multiple table */ | ||
528 | #define ML 2 | ||
529 | static const UINT8 mul_tab[16]= { | ||
530 | /* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */ | ||
531 | ML/2, 1*ML, 2*ML, 3*ML, 4*ML, 5*ML, 6*ML, 7*ML, | ||
532 | 8*ML, 9*ML,10*ML,10*ML,12*ML,12*ML,15*ML,15*ML | ||
533 | }; | ||
534 | #undef ML | ||
535 | |||
536 | /* TL_TAB_LEN is calculated as: | ||
537 | * 12 - sinus amplitude bits (Y axis) | ||
538 | * 2 - sinus sign bit (Y axis) | ||
539 | * TL_RES_LEN - sinus resolution (X axis) | ||
540 | */ | ||
541 | #define TL_TAB_LEN (12*2*TL_RES_LEN) | ||
542 | static signed int tl_tab[TL_TAB_LEN]; | ||
543 | |||
544 | #define ENV_QUIET (TL_TAB_LEN>>4) | ||
545 | |||
546 | /* sin waveform table in 'decibel' scale */ | ||
547 | /* four waveforms on OPL2 type chips */ | ||
548 | static unsigned int sin_tab[SIN_LEN * 4]; | ||
549 | |||
550 | |||
551 | /* LFO Amplitude Modulation table (verified on real YM3812) | ||
552 | 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples | ||
553 | |||
554 | Length: 210 elements. | ||
555 | |||
556 | Each of the elements has to be repeated | ||
557 | exactly 64 times (on 64 consecutive samples). | ||
558 | The whole table takes: 64 * 210 = 13440 samples. | ||
559 | |||
560 | When AM = 1 data is used directly | ||
561 | When AM = 0 data is divided by 4 before being used (losing precision is important) | ||
562 | */ | ||
563 | |||
564 | #define LFO_AM_TAB_ELEMENTS 210 | ||
565 | |||
566 | static const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = { | ||
567 | 0,0,0,0,0,0,0, | ||
568 | 1,1,1,1, | ||
569 | 2,2,2,2, | ||
570 | 3,3,3,3, | ||
571 | 4,4,4,4, | ||
572 | 5,5,5,5, | ||
573 | 6,6,6,6, | ||
574 | 7,7,7,7, | ||
575 | 8,8,8,8, | ||
576 | 9,9,9,9, | ||
577 | 10,10,10,10, | ||
578 | 11,11,11,11, | ||
579 | 12,12,12,12, | ||
580 | 13,13,13,13, | ||
581 | 14,14,14,14, | ||
582 | 15,15,15,15, | ||
583 | 16,16,16,16, | ||
584 | 17,17,17,17, | ||
585 | 18,18,18,18, | ||
586 | 19,19,19,19, | ||
587 | 20,20,20,20, | ||
588 | 21,21,21,21, | ||
589 | 22,22,22,22, | ||
590 | 23,23,23,23, | ||
591 | 24,24,24,24, | ||
592 | 25,25,25,25, | ||
593 | 26,26,26, | ||
594 | 25,25,25,25, | ||
595 | 24,24,24,24, | ||
596 | 23,23,23,23, | ||
597 | 22,22,22,22, | ||
598 | 21,21,21,21, | ||
599 | 20,20,20,20, | ||
600 | 19,19,19,19, | ||
601 | 18,18,18,18, | ||
602 | 17,17,17,17, | ||
603 | 16,16,16,16, | ||
604 | 15,15,15,15, | ||
605 | 14,14,14,14, | ||
606 | 13,13,13,13, | ||
607 | 12,12,12,12, | ||
608 | 11,11,11,11, | ||
609 | 10,10,10,10, | ||
610 | 9,9,9,9, | ||
611 | 8,8,8,8, | ||
612 | 7,7,7,7, | ||
613 | 6,6,6,6, | ||
614 | 5,5,5,5, | ||
615 | 4,4,4,4, | ||
616 | 3,3,3,3, | ||
617 | 2,2,2,2, | ||
618 | 1,1,1,1 | ||
619 | }; | ||
620 | |||
621 | /* LFO Phase Modulation table (verified on real YM3812) */ | ||
622 | static const INT8 lfo_pm_table[8*8*2] = { | ||
623 | /* FNUM2/FNUM = 00 0xxxxxxx (0x0000) */ | ||
624 | 0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/ | ||
625 | 0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 1*/ | ||
626 | |||
627 | /* FNUM2/FNUM = 00 1xxxxxxx (0x0080) */ | ||
628 | 0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/ | ||
629 | 1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 1*/ | ||
630 | |||
631 | /* FNUM2/FNUM = 01 0xxxxxxx (0x0100) */ | ||
632 | 1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/ | ||
633 | 2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 1*/ | ||
634 | |||
635 | /* FNUM2/FNUM = 01 1xxxxxxx (0x0180) */ | ||
636 | 1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/ | ||
637 | 3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 1*/ | ||
638 | |||
639 | /* FNUM2/FNUM = 10 0xxxxxxx (0x0200) */ | ||
640 | 2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/ | ||
641 | 4, 2, 0,-2,-4,-2, 0, 2, /*LFO PM depth = 1*/ | ||
642 | |||
643 | /* FNUM2/FNUM = 10 1xxxxxxx (0x0280) */ | ||
644 | 2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/ | ||
645 | 5, 2, 0,-2,-5,-2, 0, 2, /*LFO PM depth = 1*/ | ||
646 | |||
647 | /* FNUM2/FNUM = 11 0xxxxxxx (0x0300) */ | ||
648 | 3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/ | ||
649 | 6, 3, 0,-3,-6,-3, 0, 3, /*LFO PM depth = 1*/ | ||
650 | |||
651 | /* FNUM2/FNUM = 11 1xxxxxxx (0x0380) */ | ||
652 | 3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/ | ||
653 | 7, 3, 0,-3,-7,-3, 0, 3 /*LFO PM depth = 1*/ | ||
654 | }; | ||
655 | |||
656 | |||
657 | /* lock level of common table */ | ||
658 | static int num_lock = 0; | ||
659 | |||
660 | |||
661 | #define SLOT7_1 (&OPL->P_CH[7].SLOT[SLOT1]) | ||
662 | #define SLOT7_2 (&OPL->P_CH[7].SLOT[SLOT2]) | ||
663 | #define SLOT8_1 (&OPL->P_CH[8].SLOT[SLOT1]) | ||
664 | #define SLOT8_2 (&OPL->P_CH[8].SLOT[SLOT2]) | ||
665 | |||
666 | |||
667 | |||
668 | |||
669 | static int limit( int val, int max, int min ) { | ||
670 | if ( val > max ) | ||
671 | val = max; | ||
672 | else if ( val < min ) | ||
673 | val = min; | ||
674 | |||
675 | return val; | ||
676 | } | ||
677 | |||
678 | |||
679 | /* status set and IRQ handling */ | ||
680 | static void OPL_STATUS_SET(FM_OPL *OPL,int flag) | ||
681 | { | ||
682 | /* set status flag */ | ||
683 | OPL->status |= flag; | ||
684 | if(!(OPL->status & 0x80)) | ||
685 | { | ||
686 | if(OPL->status & OPL->statusmask) | ||
687 | { /* IRQ on */ | ||
688 | OPL->status |= 0x80; | ||
689 | /* callback user interrupt handler (IRQ is OFF to ON) */ | ||
690 | if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1); | ||
691 | } | ||
692 | } | ||
693 | } | ||
694 | |||
695 | /* status reset and IRQ handling */ | ||
696 | static void OPL_STATUS_RESET(FM_OPL *OPL,int flag) | ||
697 | { | ||
698 | /* reset status flag */ | ||
699 | OPL->status &=~flag; | ||
700 | if((OPL->status & 0x80)) | ||
701 | { | ||
702 | if (!(OPL->status & OPL->statusmask) ) | ||
703 | { | ||
704 | OPL->status &= 0x7f; | ||
705 | /* callback user interrupt handler (IRQ is ON to OFF) */ | ||
706 | if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0); | ||
707 | } | ||
708 | } | ||
709 | } | ||
710 | |||
711 | /* IRQ mask set */ | ||
712 | static void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag) | ||
713 | { | ||
714 | OPL->statusmask = flag; | ||
715 | /* IRQ handling check */ | ||
716 | OPL_STATUS_SET(OPL,0); | ||
717 | OPL_STATUS_RESET(OPL,0); | ||
718 | } | ||
719 | |||
720 | |||
721 | /* advance LFO to next sample */ | ||
722 | static void advance_lfo(FM_OPL *OPL) | ||
723 | { | ||
724 | UINT8 tmp; | ||
725 | |||
726 | /* LFO */ | ||
727 | OPL->lfo_am_cnt += OPL->lfo_am_inc; | ||
728 | // if (OPL->lfo_am_cnt >= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH) ) /* lfo_am_table is 210 elements long */ | ||
729 | // OPL->lfo_am_cnt -= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH); | ||
730 | if (OPL->lfo_am_cnt >= (LFO_AM_TAB_ELEMENTS<<LFO_SH) ) /* lfo_am_table is 210 elements long */ | ||
731 | OPL->lfo_am_cnt -= (LFO_AM_TAB_ELEMENTS<<LFO_SH); | ||
732 | |||
733 | tmp = lfo_am_table[ OPL->lfo_am_cnt >> LFO_SH ]; | ||
734 | |||
735 | if (OPL->lfo_am_depth) | ||
736 | OPL->LFO_AM = tmp; | ||
737 | else | ||
738 | OPL->LFO_AM = tmp>>2; | ||
739 | |||
740 | OPL->lfo_pm_cnt += OPL->lfo_pm_inc; | ||
741 | OPL->LFO_PM = ((OPL->lfo_pm_cnt>>LFO_SH) & 7) | OPL->lfo_pm_depth_range; | ||
742 | } | ||
743 | |||
744 | /* advance to next sample */ | ||
745 | static void advance(FM_OPL *OPL) | ||
746 | { | ||
747 | OPL_CH *CH; | ||
748 | OPL_SLOT *op; | ||
749 | int i; | ||
750 | |||
751 | OPL->eg_timer += OPL->eg_timer_add; | ||
752 | |||
753 | while (OPL->eg_timer >= OPL->eg_timer_overflow) | ||
754 | { | ||
755 | OPL->eg_timer -= OPL->eg_timer_overflow; | ||
756 | |||
757 | OPL->eg_cnt++; | ||
758 | |||
759 | for (i=0; i<9*2; i++) | ||
760 | { | ||
761 | CH = &OPL->P_CH[i/2]; | ||
762 | op = &CH->SLOT[i&1]; | ||
763 | |||
764 | /* Envelope Generator */ | ||
765 | switch(op->state) | ||
766 | { | ||
767 | case EG_ATT: /* attack phase */ | ||
768 | if ( !(OPL->eg_cnt & ((1<<op->eg_sh_ar)-1) ) ) | ||
769 | { | ||
770 | op->volume += (~op->volume * | ||
771 | (eg_inc[op->eg_sel_ar + ((OPL->eg_cnt>>op->eg_sh_ar)&7)]) | ||
772 | ) >>3; | ||
773 | |||
774 | if (op->volume <= MIN_ATT_INDEX) | ||
775 | { | ||
776 | op->volume = MIN_ATT_INDEX; | ||
777 | op->state = EG_DEC; | ||
778 | } | ||
779 | |||
780 | } | ||
781 | break; | ||
782 | |||
783 | case EG_DEC: /* decay phase */ | ||
784 | if ( !(OPL->eg_cnt & ((1<<op->eg_sh_dr)-1) ) ) | ||
785 | { | ||
786 | op->volume += eg_inc[op->eg_sel_dr + ((OPL->eg_cnt>>op->eg_sh_dr)&7)]; | ||
787 | |||
788 | if ( (UINT32) op->volume >= op->sl ) | ||
789 | op->state = EG_SUS; | ||
790 | |||
791 | } | ||
792 | break; | ||
793 | |||
794 | case EG_SUS: /* sustain phase */ | ||
795 | |||
796 | /* this is important behaviour: | ||
797 | one can change percusive/non-percussive modes on the fly and | ||
798 | the chip will remain in sustain phase - verified on real YM3812 */ | ||
799 | |||
800 | if(op->eg_type) /* non-percussive mode */ | ||
801 | { | ||
802 | /* do nothing */ | ||
803 | } | ||
804 | else /* percussive mode */ | ||
805 | { | ||
806 | /* during sustain phase chip adds Release Rate (in percussive mode) */ | ||
807 | if ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) ) | ||
808 | { | ||
809 | op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)]; | ||
810 | |||
811 | if ( op->volume >= MAX_ATT_INDEX ) | ||
812 | op->volume = MAX_ATT_INDEX; | ||
813 | } | ||
814 | /* else do nothing in sustain phase */ | ||
815 | } | ||
816 | break; | ||
817 | |||
818 | case EG_REL: /* release phase */ | ||
819 | if ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) ) | ||
820 | { | ||
821 | op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)]; | ||
822 | |||
823 | if ( op->volume >= MAX_ATT_INDEX ) | ||
824 | { | ||
825 | op->volume = MAX_ATT_INDEX; | ||
826 | op->state = EG_OFF; | ||
827 | } | ||
828 | |||
829 | } | ||
830 | break; | ||
831 | |||
832 | default: | ||
833 | break; | ||
834 | } | ||
835 | } | ||
836 | } | ||
837 | |||
838 | for (i=0; i<9*2; i++) | ||
839 | { | ||
840 | CH = &OPL->P_CH[i/2]; | ||
841 | op = &CH->SLOT[i&1]; | ||
842 | |||
843 | /* Phase Generator */ | ||
844 | if(op->vib) | ||
845 | { | ||
846 | UINT8 block; | ||
847 | unsigned int block_fnum = CH->block_fnum; | ||
848 | |||
849 | unsigned int fnum_lfo = (block_fnum&0x0380) >> 7; | ||
850 | |||
851 | signed int lfo_fn_table_index_offset = lfo_pm_table[OPL->LFO_PM + 16*fnum_lfo ]; | ||
852 | |||
853 | if (lfo_fn_table_index_offset) /* LFO phase modulation active */ | ||
854 | { | ||
855 | block_fnum += lfo_fn_table_index_offset; | ||
856 | block = (block_fnum&0x1c00) >> 10; | ||
857 | op->Cnt += (OPL->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul; | ||
858 | } | ||
859 | else /* LFO phase modulation = zero */ | ||
860 | { | ||
861 | op->Cnt += op->Incr; | ||
862 | } | ||
863 | } | ||
864 | else /* LFO phase modulation disabled for this operator */ | ||
865 | { | ||
866 | op->Cnt += op->Incr; | ||
867 | } | ||
868 | } | ||
869 | |||
870 | /* The Noise Generator of the YM3812 is 23-bit shift register. | ||
871 | * Period is equal to 2^23-2 samples. | ||
872 | * Register works at sampling frequency of the chip, so output | ||
873 | * can change on every sample. | ||
874 | * | ||
875 | * Output of the register and input to the bit 22 is: | ||
876 | * bit0 XOR bit14 XOR bit15 XOR bit22 | ||
877 | * | ||
878 | * Simply use bit 22 as the noise output. | ||
879 | */ | ||
880 | |||
881 | OPL->noise_p += OPL->noise_f; | ||
882 | i = OPL->noise_p >> FREQ_SH; /* number of events (shifts of the shift register) */ | ||
883 | OPL->noise_p &= FREQ_MASK; | ||
884 | while (i) | ||
885 | { | ||
886 | /* | ||
887 | UINT32 j; | ||
888 | j = ( (OPL->noise_rng) ^ (OPL->noise_rng>>14) ^ (OPL->noise_rng>>15) ^ (OPL->noise_rng>>22) ) & 1; | ||
889 | OPL->noise_rng = (j<<22) | (OPL->noise_rng>>1); | ||
890 | */ | ||
891 | |||
892 | /* | ||
893 | Instead of doing all the logic operations above, we | ||
894 | use a trick here (and use bit 0 as the noise output). | ||
895 | The difference is only that the noise bit changes one | ||
896 | step ahead. This doesn't matter since we don't know | ||
897 | what is real state of the noise_rng after the reset. | ||
898 | */ | ||
899 | |||
900 | if (OPL->noise_rng & 1) OPL->noise_rng ^= 0x800302; | ||
901 | OPL->noise_rng >>= 1; | ||
902 | |||
903 | i--; | ||
904 | } | ||
905 | } | ||
906 | |||
907 | |||
908 | static signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab) | ||
909 | { | ||
910 | UINT32 p; | ||
911 | |||
912 | p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK) ]; | ||
913 | |||
914 | if (p >= TL_TAB_LEN) | ||
915 | return 0; | ||
916 | return tl_tab[p]; | ||
917 | } | ||
918 | |||
919 | static signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab) | ||
920 | { | ||
921 | UINT32 p; | ||
922 | |||
923 | p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + pm )) >> FREQ_SH ) & SIN_MASK) ]; | ||
924 | |||
925 | if (p >= TL_TAB_LEN) | ||
926 | return 0; | ||
927 | return tl_tab[p]; | ||
928 | } | ||
929 | |||
930 | |||
931 | #define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (OPL->LFO_AM & (OP)->AMmask)) | ||
932 | |||
933 | /* calculate output */ | ||
934 | static void OPL_CALC_CH( FM_OPL *OPL, OPL_CH *CH ) | ||
935 | { | ||
936 | OPL_SLOT *SLOT; | ||
937 | unsigned int env; | ||
938 | signed int out; | ||
939 | |||
940 | OPL->phase_modulation = 0; | ||
941 | |||
942 | /* SLOT 1 */ | ||
943 | SLOT = &CH->SLOT[SLOT1]; | ||
944 | env = volume_calc(SLOT); | ||
945 | out = SLOT->op1_out[0] + SLOT->op1_out[1]; | ||
946 | SLOT->op1_out[0] = SLOT->op1_out[1]; | ||
947 | |||
948 | //INT32 a; | ||
949 | //memcpy(&a, SLOT->connect1, sizeof(a)); | ||
950 | //a += SLOT->op1_out[0]; | ||
951 | //memcpy(SLOT->connect1, &a, sizeof(a)); | ||
952 | |||
953 | *SLOT->connect1 += SLOT->op1_out[0]; // alignment issue on arm | ||
954 | SLOT->op1_out[1] = 0; | ||
955 | if( env < ENV_QUIET ) | ||
956 | { | ||
957 | if (!SLOT->FB) | ||
958 | out = 0; | ||
959 | SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable ); | ||
960 | } | ||
961 | /* SLOT 2 */ | ||
962 | SLOT++; | ||
963 | env = volume_calc(SLOT); | ||
964 | if( env < ENV_QUIET ) | ||
965 | { | ||
966 | OPL->output[0] += op_calc(SLOT->Cnt, env, OPL->phase_modulation, SLOT->wavetable); | ||
967 | } | ||
968 | } | ||
969 | |||
970 | /* | ||
971 | operators used in the rhythm sounds generation process: | ||
972 | |||
973 | Envelope Generator: | ||
974 | |||
975 | channel operator register number Bass High Snare Tom Top | ||
976 | / slot number TL ARDR SLRR Wave Drum Hat Drum Tom Cymbal | ||
977 | 6 / 0 12 50 70 90 f0 + | ||
978 | 6 / 1 15 53 73 93 f3 + | ||
979 | 7 / 0 13 51 71 91 f1 + | ||
980 | 7 / 1 16 54 74 94 f4 + | ||
981 | 8 / 0 14 52 72 92 f2 + | ||
982 | 8 / 1 17 55 75 95 f5 + | ||
983 | |||
984 | Phase Generator: | ||
985 | |||
986 | channel operator register number Bass High Snare Tom Top | ||
987 | / slot number MULTIPLE Drum Hat Drum Tom Cymbal | ||
988 | 6 / 0 12 30 + | ||
989 | 6 / 1 15 33 + | ||
990 | 7 / 0 13 31 + + + | ||
991 | 7 / 1 16 34 ----- n o t u s e d ----- | ||
992 | 8 / 0 14 32 + | ||
993 | 8 / 1 17 35 + + | ||
994 | |||
995 | channel operator register number Bass High Snare Tom Top | ||
996 | number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal | ||
997 | 6 12,15 B6 A6 + | ||
998 | |||
999 | 7 13,16 B7 A7 + + + | ||
1000 | |||
1001 | 8 14,17 B8 A8 + + + | ||
1002 | |||
1003 | */ | ||
1004 | |||
1005 | /* calculate rhythm */ | ||
1006 | |||
1007 | static void OPL_CALC_RH( FM_OPL *OPL, OPL_CH *CH, unsigned int noise ) | ||
1008 | { | ||
1009 | OPL_SLOT *SLOT; | ||
1010 | signed int out; | ||
1011 | unsigned int env; | ||
1012 | |||
1013 | |||
1014 | /* Bass Drum (verified on real YM3812): | ||
1015 | - depends on the channel 6 'connect' register: | ||
1016 | when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out) | ||
1017 | when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored | ||
1018 | - output sample always is multiplied by 2 | ||
1019 | */ | ||
1020 | |||
1021 | OPL->phase_modulation = 0; | ||
1022 | /* SLOT 1 */ | ||
1023 | SLOT = &CH[6].SLOT[SLOT1]; | ||
1024 | env = volume_calc(SLOT); | ||
1025 | |||
1026 | out = SLOT->op1_out[0] + SLOT->op1_out[1]; | ||
1027 | SLOT->op1_out[0] = SLOT->op1_out[1]; | ||
1028 | |||
1029 | if (!SLOT->CON) | ||
1030 | OPL->phase_modulation = SLOT->op1_out[0]; | ||
1031 | /* else ignore output of operator 1 */ | ||
1032 | |||
1033 | SLOT->op1_out[1] = 0; | ||
1034 | if( env < ENV_QUIET ) | ||
1035 | { | ||
1036 | if (!SLOT->FB) | ||
1037 | out = 0; | ||
1038 | SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable ); | ||
1039 | } | ||
1040 | |||
1041 | /* SLOT 2 */ | ||
1042 | SLOT++; | ||
1043 | env = volume_calc(SLOT); | ||
1044 | if( env < ENV_QUIET ) | ||
1045 | OPL->output[0] += op_calc(SLOT->Cnt, env, OPL->phase_modulation, SLOT->wavetable) * 2; | ||
1046 | |||
1047 | |||
1048 | /* Phase generation is based on: */ | ||
1049 | /* HH (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) */ | ||
1050 | /* SD (16) channel 7->slot 1 */ | ||
1051 | /* TOM (14) channel 8->slot 1 */ | ||
1052 | /* TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) */ | ||
1053 | |||
1054 | /* Envelope generation based on: */ | ||
1055 | /* HH channel 7->slot1 */ | ||
1056 | /* SD channel 7->slot2 */ | ||
1057 | /* TOM channel 8->slot1 */ | ||
1058 | /* TOP channel 8->slot2 */ | ||
1059 | |||
1060 | |||
1061 | /* The following formulas can be well optimized. | ||
1062 | I leave them in direct form for now (in case I've missed something). | ||
1063 | */ | ||
1064 | |||
1065 | /* High Hat (verified on real YM3812) */ | ||
1066 | env = volume_calc(SLOT7_1); | ||
1067 | if( env < ENV_QUIET ) | ||
1068 | { | ||
1069 | /* high hat phase generation: | ||
1070 | phase = d0 or 234 (based on frequency only) | ||
1071 | phase = 34 or 2d0 (based on noise) | ||
1072 | */ | ||
1073 | |||
1074 | /* base frequency derived from operator 1 in channel 7 */ | ||
1075 | unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1; | ||
1076 | unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1; | ||
1077 | unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1; | ||
1078 | |||
1079 | unsigned char res1 = (bit2 ^ bit7) | bit3; | ||
1080 | |||
1081 | /* when res1 = 0 phase = 0x000 | 0xd0; */ | ||
1082 | /* when res1 = 1 phase = 0x200 | (0xd0>>2); */ | ||
1083 | UINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0; | ||
1084 | |||
1085 | /* enable gate based on frequency of operator 2 in channel 8 */ | ||
1086 | unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1; | ||
1087 | unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1; | ||
1088 | |||
1089 | unsigned char res2 = (bit3e ^ bit5e); | ||
1090 | |||
1091 | /* when res2 = 0 pass the phase from calculation above (res1); */ | ||
1092 | /* when res2 = 1 phase = 0x200 | (0xd0>>2); */ | ||
1093 | if (res2) | ||
1094 | phase = (0x200|(0xd0>>2)); | ||
1095 | |||
1096 | |||
1097 | /* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */ | ||
1098 | /* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */ | ||
1099 | if (phase&0x200) | ||
1100 | { | ||
1101 | if (noise) | ||
1102 | phase = 0x200|0xd0; | ||
1103 | } | ||
1104 | else | ||
1105 | /* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */ | ||
1106 | /* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */ | ||
1107 | { | ||
1108 | if (noise) | ||
1109 | phase = 0xd0>>2; | ||
1110 | } | ||
1111 | |||
1112 | OPL->output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_1->wavetable) * 2; | ||
1113 | } | ||
1114 | |||
1115 | /* Snare Drum (verified on real YM3812) */ | ||
1116 | env = volume_calc(SLOT7_2); | ||
1117 | if( env < ENV_QUIET ) | ||
1118 | { | ||
1119 | /* base frequency derived from operator 1 in channel 7 */ | ||
1120 | unsigned char bit8 = ((SLOT7_1->Cnt>>FREQ_SH)>>8)&1; | ||
1121 | |||
1122 | /* when bit8 = 0 phase = 0x100; */ | ||
1123 | /* when bit8 = 1 phase = 0x200; */ | ||
1124 | UINT32 phase = bit8 ? 0x200 : 0x100; | ||
1125 | |||
1126 | /* Noise bit XOR'es phase by 0x100 */ | ||
1127 | /* when noisebit = 0 pass the phase from calculation above */ | ||
1128 | /* when noisebit = 1 phase ^= 0x100; */ | ||
1129 | /* in other words: phase ^= (noisebit<<8); */ | ||
1130 | if (noise) | ||
1131 | phase ^= 0x100; | ||
1132 | |||
1133 | OPL->output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_2->wavetable) * 2; | ||
1134 | } | ||
1135 | |||
1136 | /* Tom Tom (verified on real YM3812) */ | ||
1137 | env = volume_calc(SLOT8_1); | ||
1138 | if( env < ENV_QUIET ) | ||
1139 | OPL->output[0] += op_calc(SLOT8_1->Cnt, env, 0, SLOT8_1->wavetable) * 2; | ||
1140 | |||
1141 | /* Top Cymbal (verified on real YM3812) */ | ||
1142 | env = volume_calc(SLOT8_2); | ||
1143 | if( env < ENV_QUIET ) | ||
1144 | { | ||
1145 | /* base frequency derived from operator 1 in channel 7 */ | ||
1146 | unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1; | ||
1147 | unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1; | ||
1148 | unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1; | ||
1149 | |||
1150 | unsigned char res1 = (bit2 ^ bit7) | bit3; | ||
1151 | |||
1152 | /* when res1 = 0 phase = 0x000 | 0x100; */ | ||
1153 | /* when res1 = 1 phase = 0x200 | 0x100; */ | ||
1154 | UINT32 phase = res1 ? 0x300 : 0x100; | ||
1155 | |||
1156 | /* enable gate based on frequency of operator 2 in channel 8 */ | ||
1157 | unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1; | ||
1158 | unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1; | ||
1159 | |||
1160 | unsigned char res2 = (bit3e ^ bit5e); | ||
1161 | /* when res2 = 0 pass the phase from calculation above (res1); */ | ||
1162 | /* when res2 = 1 phase = 0x200 | 0x100; */ | ||
1163 | if (res2) | ||
1164 | phase = 0x300; | ||
1165 | |||
1166 | OPL->output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT8_2->wavetable) * 2; | ||
1167 | } | ||
1168 | } | ||
1169 | |||
1170 | |||
1171 | /* generic table initialize */ | ||
1172 | static int init_tables(void) | ||
1173 | { | ||
1174 | signed int i,x; | ||
1175 | signed int n; | ||
1176 | double o,m; | ||
1177 | |||
1178 | |||
1179 | for (x=0; x<TL_RES_LEN; x++) | ||
1180 | { | ||
1181 | m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0); | ||
1182 | m = floor(m); | ||
1183 | |||
1184 | /* we never reach (1<<16) here due to the (x+1) */ | ||
1185 | /* result fits within 16 bits at maximum */ | ||
1186 | |||
1187 | n = (int)m; /* 16 bits here */ | ||
1188 | n >>= 4; /* 12 bits here */ | ||
1189 | if (n&1) /* round to nearest */ | ||
1190 | n = (n>>1)+1; | ||
1191 | else | ||
1192 | n = n>>1; | ||
1193 | /* 11 bits here (rounded) */ | ||
1194 | n <<= 1; /* 12 bits here (as in real chip) */ | ||
1195 | tl_tab[ x*2 + 0 ] = n; | ||
1196 | tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ]; | ||
1197 | |||
1198 | for (i=1; i<12; i++) | ||
1199 | { | ||
1200 | tl_tab[ x*2+0 + i*2*TL_RES_LEN ] = tl_tab[ x*2+0 ]>>i; | ||
1201 | tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ]; | ||
1202 | } | ||
1203 | #if 0 | ||
1204 | logerror("tl %04i", x*2); | ||
1205 | for (i=0; i<12; i++) | ||
1206 | logerror(", [%02i] %5i", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ] ); | ||
1207 | logerror("\n"); | ||
1208 | #endif | ||
1209 | } | ||
1210 | /*logerror("FMOPL.C: TL_TAB_LEN = %i elements (%i bytes)\n",TL_TAB_LEN, (int)sizeof(tl_tab));*/ | ||
1211 | |||
1212 | |||
1213 | for (i=0; i<SIN_LEN; i++) | ||
1214 | { | ||
1215 | /* non-standard sinus */ | ||
1216 | m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */ | ||
1217 | |||
1218 | /* we never reach zero here due to ((i*2)+1) */ | ||
1219 | |||
1220 | if (m>0.0) | ||
1221 | o = 8*log(1.0/m)/log(2.0); /* convert to 'decibels' */ | ||
1222 | else | ||
1223 | o = 8*log(-1.0/m)/log(2.0); /* convert to 'decibels' */ | ||
1224 | |||
1225 | o = o / (ENV_STEP/4); | ||
1226 | |||
1227 | n = (int)(2.0*o); | ||
1228 | if (n&1) /* round to nearest */ | ||
1229 | n = (n>>1)+1; | ||
1230 | else | ||
1231 | n = n>>1; | ||
1232 | |||
1233 | sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 ); | ||
1234 | |||
1235 | /*logerror("FMOPL.C: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\n", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/ | ||
1236 | } | ||
1237 | |||
1238 | for (i=0; i<SIN_LEN; i++) | ||
1239 | { | ||
1240 | /* waveform 1: __ __ */ | ||
1241 | /* / \____/ \____*/ | ||
1242 | /* output only first half of the sinus waveform (positive one) */ | ||
1243 | |||
1244 | if (i & (1<<(SIN_BITS-1)) ) | ||
1245 | sin_tab[1*SIN_LEN+i] = TL_TAB_LEN; | ||
1246 | else | ||
1247 | sin_tab[1*SIN_LEN+i] = sin_tab[i]; | ||
1248 | |||
1249 | /* waveform 2: __ __ __ __ */ | ||
1250 | /* / \/ \/ \/ \*/ | ||
1251 | /* abs(sin) */ | ||
1252 | |||
1253 | sin_tab[2*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>1) ]; | ||
1254 | |||
1255 | /* waveform 3: _ _ _ _ */ | ||
1256 | /* / |_/ |_/ |_/ |_*/ | ||
1257 | /* abs(output only first quarter of the sinus waveform) */ | ||
1258 | |||
1259 | if (i & (1<<(SIN_BITS-2)) ) | ||
1260 | sin_tab[3*SIN_LEN+i] = TL_TAB_LEN; | ||
1261 | else | ||
1262 | sin_tab[3*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>2)]; | ||
1263 | |||
1264 | /*logerror("FMOPL.C: sin1[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] ); | ||
1265 | logerror("FMOPL.C: sin2[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[2*SIN_LEN+i], tl_tab[sin_tab[2*SIN_LEN+i]] ); | ||
1266 | logerror("FMOPL.C: sin3[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[3*SIN_LEN+i], tl_tab[sin_tab[3*SIN_LEN+i]] );*/ | ||
1267 | } | ||
1268 | /*logerror("FMOPL.C: ENV_QUIET= %08x (dec*8=%i)\n", ENV_QUIET, ENV_QUIET*8 );*/ | ||
1269 | |||
1270 | |||
1271 | #ifdef SAVE_SAMPLE | ||
1272 | sample[0]=fopen("sampsum.pcm","wb"); | ||
1273 | #endif | ||
1274 | |||
1275 | return 1; | ||
1276 | } | ||
1277 | |||
1278 | static void OPLCloseTable( void ) | ||
1279 | { | ||
1280 | #ifdef SAVE_SAMPLE | ||
1281 | fclose(sample[0]); | ||
1282 | #endif | ||
1283 | } | ||
1284 | |||
1285 | |||
1286 | |||
1287 | static void OPL_initalize(FM_OPL *OPL) | ||
1288 | { | ||
1289 | int i; | ||
1290 | |||
1291 | /* frequency base */ | ||
1292 | OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / 72.0) / OPL->rate : 0; | ||
1293 | #if 0 | ||
1294 | OPL->rate = (double)OPL->clock / 72.0; | ||
1295 | OPL->freqbase = 1.0; | ||
1296 | #endif | ||
1297 | |||
1298 | /*logerror("freqbase=%f\n", OPL->freqbase);*/ | ||
1299 | |||
1300 | /* Timer base time */ | ||
1301 | OPL->TimerBase = 1.0 / ((double)OPL->clock / 72.0 ); | ||
1302 | |||
1303 | /* make fnumber -> increment counter table */ | ||
1304 | for( i=0 ; i < 1024 ; i++ ) | ||
1305 | { | ||
1306 | /* opn phase increment counter = 20bit */ | ||
1307 | OPL->fn_tab[i] = (UINT32)( (double)i * 64 * OPL->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */ | ||
1308 | #if 0 | ||
1309 | logerror("FMOPL.C: fn_tab[%4i] = %08x (dec=%8i)\n", | ||
1310 | i, OPL->fn_tab[i]>>6, OPL->fn_tab[i]>>6 ); | ||
1311 | #endif | ||
1312 | } | ||
1313 | |||
1314 | #if 0 | ||
1315 | for( i=0 ; i < 16 ; i++ ) | ||
1316 | { | ||
1317 | logerror("FMOPL.C: sl_tab[%i] = %08x\n", | ||
1318 | i, sl_tab[i] ); | ||
1319 | } | ||
1320 | for( i=0 ; i < 8 ; i++ ) | ||
1321 | { | ||
1322 | int j; | ||
1323 | logerror("FMOPL.C: ksl_tab[oct=%2i] =",i); | ||
1324 | for (j=0; j<16; j++) | ||
1325 | { | ||
1326 | logerror("%08x ", (UINT32)(ksl_tab[i*16+j]) ); | ||
1327 | } | ||
1328 | logerror("\n"); | ||
1329 | } | ||
1330 | #endif | ||
1331 | |||
1332 | |||
1333 | /* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */ | ||
1334 | /* One entry from LFO_AM_TABLE lasts for 64 samples */ | ||
1335 | OPL->lfo_am_inc = (UINT32) ((1.0 / 64.0 ) * (1<<LFO_SH) * OPL->freqbase); | ||
1336 | |||
1337 | /* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */ | ||
1338 | OPL->lfo_pm_inc = (UINT32) ((1.0 / 1024.0) * (1<<LFO_SH) * OPL->freqbase); | ||
1339 | |||
1340 | /*logerror ("OPL->lfo_am_inc = %8x ; OPL->lfo_pm_inc = %8x\n", OPL->lfo_am_inc, OPL->lfo_pm_inc);*/ | ||
1341 | |||
1342 | /* Noise generator: a step takes 1 sample */ | ||
1343 | OPL->noise_f = (UINT32) ((1.0 / 1.0) * (1<<FREQ_SH) * OPL->freqbase); | ||
1344 | |||
1345 | OPL->eg_timer_add = (UINT32) ((1<<EG_SH) * OPL->freqbase); | ||
1346 | OPL->eg_timer_overflow = ( 1 ) * (1<<EG_SH); | ||
1347 | /*logerror("OPLinit eg_timer_add=%8x eg_timer_overflow=%8x\n", OPL->eg_timer_add, OPL->eg_timer_overflow);*/ | ||
1348 | |||
1349 | } | ||
1350 | |||
1351 | static void FM_KEYON(OPL_SLOT *SLOT, UINT32 key_set) | ||
1352 | { | ||
1353 | if( !SLOT->key ) | ||
1354 | { | ||
1355 | /* restart Phase Generator */ | ||
1356 | SLOT->Cnt = 0; | ||
1357 | /* phase -> Attack */ | ||
1358 | SLOT->state = EG_ATT; | ||
1359 | } | ||
1360 | SLOT->key |= key_set; | ||
1361 | } | ||
1362 | |||
1363 | static void FM_KEYOFF(OPL_SLOT *SLOT, UINT32 key_clr) | ||
1364 | { | ||
1365 | if( SLOT->key ) | ||
1366 | { | ||
1367 | SLOT->key &= key_clr; | ||
1368 | |||
1369 | if( !SLOT->key ) | ||
1370 | { | ||
1371 | /* phase -> Release */ | ||
1372 | if (SLOT->state>EG_REL) | ||
1373 | SLOT->state = EG_REL; | ||
1374 | } | ||
1375 | } | ||
1376 | } | ||
1377 | |||
1378 | /* update phase increment counter of operator (also update the EG rates if necessary) */ | ||
1379 | static void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT) | ||
1380 | { | ||
1381 | int ksr; | ||
1382 | |||
1383 | /* (frequency) phase increment counter */ | ||
1384 | SLOT->Incr = CH->fc * SLOT->mul; | ||
1385 | ksr = CH->kcode >> SLOT->KSR; | ||
1386 | |||
1387 | if( SLOT->ksr != ksr ) | ||
1388 | { | ||
1389 | SLOT->ksr = ksr; | ||
1390 | |||
1391 | /* calculate envelope generator rates */ | ||
1392 | if ((SLOT->ar + SLOT->ksr) < 16+62) | ||
1393 | { | ||
1394 | SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; | ||
1395 | SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; | ||
1396 | } | ||
1397 | else | ||
1398 | { | ||
1399 | SLOT->eg_sh_ar = 0; | ||
1400 | SLOT->eg_sel_ar = 13*RATE_STEPS; | ||
1401 | } | ||
1402 | SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ]; | ||
1403 | SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ]; | ||
1404 | SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ]; | ||
1405 | SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ]; | ||
1406 | } | ||
1407 | } | ||
1408 | |||
1409 | /* set multi,am,vib,EG-TYP,KSR,mul */ | ||
1410 | static void set_mul(FM_OPL *OPL,int slot,int v) | ||
1411 | { | ||
1412 | OPL_CH *CH = &OPL->P_CH[slot/2]; | ||
1413 | OPL_SLOT *SLOT = &CH->SLOT[slot&1]; | ||
1414 | |||
1415 | SLOT->mul = mul_tab[v&0x0f]; | ||
1416 | SLOT->KSR = (v&0x10) ? 0 : 2; | ||
1417 | SLOT->eg_type = (v&0x20); | ||
1418 | SLOT->vib = (v&0x40); | ||
1419 | SLOT->AMmask = (v&0x80) ? ~0 : 0; | ||
1420 | CALC_FCSLOT(CH,SLOT); | ||
1421 | } | ||
1422 | |||
1423 | /* set ksl & tl */ | ||
1424 | static void set_ksl_tl(FM_OPL *OPL,int slot,int v) | ||
1425 | { | ||
1426 | #if 0 | ||
1427 | OPL_CH *CH = &OPL->P_CH[slot/2]; | ||
1428 | OPL_SLOT *SLOT = &CH->SLOT[slot&1]; | ||
1429 | |||
1430 | SLOT->ksl = ksl_shift[v >> 6]; | ||
1431 | SLOT->TL = (v&0x3f)<<(ENV_BITS-1-7); /* 7 bits TL (bit 6 = always 0) */ | ||
1432 | |||
1433 | SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); | ||
1434 | #else | ||
1435 | OPL_CH *CH = &OPL->P_CH[slot/2]; | ||
1436 | OPL_SLOT *SLOT = &CH->SLOT[slot&1]; | ||
1437 | int ksl = v>>6; /* 0 / 1.5 / 3.0 / 6.0 dB/OCT */ | ||
1438 | |||
1439 | SLOT->ksl = ksl ? 3-ksl : 31; | ||
1440 | SLOT->TL = (v&0x3f)<<(ENV_BITS-1-7); /* 7 bits TL (bit 6 = always 0) */ | ||
1441 | |||
1442 | SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); | ||
1443 | #endif | ||
1444 | } | ||
1445 | |||
1446 | /* set attack rate & decay rate */ | ||
1447 | static void set_ar_dr(FM_OPL *OPL,int slot,int v) | ||
1448 | { | ||
1449 | OPL_CH *CH = &OPL->P_CH[slot/2]; | ||
1450 | OPL_SLOT *SLOT = &CH->SLOT[slot&1]; | ||
1451 | |||
1452 | SLOT->ar = (v>>4) ? 16 + ((v>>4) <<2) : 0; | ||
1453 | |||
1454 | if ((SLOT->ar + SLOT->ksr) < 16+62) | ||
1455 | { | ||
1456 | SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; | ||
1457 | SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; | ||
1458 | } | ||
1459 | else | ||
1460 | { | ||
1461 | SLOT->eg_sh_ar = 0; | ||
1462 | SLOT->eg_sel_ar = 13*RATE_STEPS; | ||
1463 | } | ||
1464 | |||
1465 | SLOT->dr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0; | ||
1466 | SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ]; | ||
1467 | SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ]; | ||
1468 | } | ||
1469 | |||
1470 | /* set sustain level & release rate */ | ||
1471 | static void set_sl_rr(FM_OPL *OPL,int slot,int v) | ||
1472 | { | ||
1473 | OPL_CH *CH = &OPL->P_CH[slot/2]; | ||
1474 | OPL_SLOT *SLOT = &CH->SLOT[slot&1]; | ||
1475 | |||
1476 | SLOT->sl = sl_tab[ v>>4 ]; | ||
1477 | |||
1478 | SLOT->rr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0; | ||
1479 | SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ]; | ||
1480 | SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ]; | ||
1481 | } | ||
1482 | |||
1483 | |||
1484 | /* write a value v to register r on OPL chip */ | ||
1485 | static void OPLWriteReg(FM_OPL *OPL, int r, int v) | ||
1486 | { | ||
1487 | OPL_CH *CH; | ||
1488 | int slot; | ||
1489 | int block_fnum; | ||
1490 | |||
1491 | |||
1492 | /* adjust bus to 8 bits */ | ||
1493 | r &= 0xff; | ||
1494 | v &= 0xff; | ||
1495 | |||
1496 | if (LOG_CYM_FILE && (cymfile) && (r!=0) ) | ||
1497 | { | ||
1498 | fprintf(cymfile, "%02x = %02x\n", r, v); | ||
1499 | } | ||
1500 | |||
1501 | |||
1502 | switch(r&0xe0) | ||
1503 | { | ||
1504 | case 0x00: /* 00-1f:control */ | ||
1505 | switch(r&0x1f) | ||
1506 | { | ||
1507 | case 0x01: /* waveform select enable */ | ||
1508 | if(OPL->type&OPL_TYPE_WAVESEL) | ||
1509 | { | ||
1510 | OPL->wavesel = v&0x20; | ||
1511 | /* do not change the waveform previously selected */ | ||
1512 | } | ||
1513 | break; | ||
1514 | case 0x02: /* Timer 1 */ | ||
1515 | OPL->T[0] = (256-v)*4; | ||
1516 | break; | ||
1517 | case 0x03: /* Timer 2 */ | ||
1518 | OPL->T[1] = (256-v)*16; | ||
1519 | break; | ||
1520 | case 0x04: /* IRQ clear / mask and Timer enable */ | ||
1521 | if(v&0x80) | ||
1522 | { /* IRQ flag clear */ | ||
1523 | OPL_STATUS_RESET(OPL,0x7f-0x08); /* don't reset BFRDY flag or we will have to call deltat module to set the flag */ | ||
1524 | } | ||
1525 | else | ||
1526 | { /* set IRQ mask ,timer enable*/ | ||
1527 | UINT8 st1 = v&1; | ||
1528 | UINT8 st2 = (v>>1)&1; | ||
1529 | |||
1530 | /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */ | ||
1531 | OPL_STATUS_RESET(OPL, v & (0x78-0x08) ); | ||
1532 | OPL_STATUSMASK_SET(OPL, (~v) & 0x78 ); | ||
1533 | |||
1534 | /* timer 2 */ | ||
1535 | if(OPL->st[1] != st2) | ||
1536 | { | ||
1537 | double period = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0; | ||
1538 | //double period = st2 ? (OPL->TimerBase * OPL->T[1]) : 0; | ||
1539 | OPL->st[1] = st2; | ||
1540 | if (OPL->timer_handler) (OPL->timer_handler)(1,period); | ||
1541 | } | ||
1542 | /* timer 1 */ | ||
1543 | if(OPL->st[0] != st1) | ||
1544 | { | ||
1545 | double period = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0; | ||
1546 | //double period = st1 ? (OPL->TimerBase * OPL->T[0]) : 0; | ||
1547 | OPL->st[0] = st1; | ||
1548 | if (OPL->timer_handler) (OPL->timer_handler)(0,period); | ||
1549 | } | ||
1550 | } | ||
1551 | break; | ||
1552 | #if BUILD_Y8950 | ||
1553 | case 0x06: /* Key Board OUT */ | ||
1554 | if(OPL->type&OPL_TYPE_KEYBOARD) | ||
1555 | { | ||
1556 | if(OPL->keyboardhandler_w) | ||
1557 | OPL->keyboardhandler_w(OPL->keyboard_param,v); | ||
1558 | else | ||
1559 | { | ||
1560 | //OPL->device->logerror("Y8950: write unmapped KEYBOARD port\n"); | ||
1561 | } | ||
1562 | } | ||
1563 | break; | ||
1564 | case 0x07: /* DELTA-T control 1 : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */ | ||
1565 | if(OPL->type&OPL_TYPE_ADPCM) | ||
1566 | YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v); | ||
1567 | break; | ||
1568 | #endif | ||
1569 | case 0x08: /* MODE,DELTA-T control 2 : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */ | ||
1570 | OPL->mode = v; | ||
1571 | #if BUILD_Y8950 | ||
1572 | if(OPL->type&OPL_TYPE_ADPCM) | ||
1573 | YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v&0x0f); /* mask 4 LSBs in register 08 for DELTA-T unit */ | ||
1574 | #endif | ||
1575 | break; | ||
1576 | |||
1577 | #if BUILD_Y8950 | ||
1578 | case 0x09: /* START ADD */ | ||
1579 | case 0x0a: | ||
1580 | case 0x0b: /* STOP ADD */ | ||
1581 | case 0x0c: | ||
1582 | case 0x0d: /* PRESCALE */ | ||
1583 | case 0x0e: | ||
1584 | case 0x0f: /* ADPCM data write */ | ||
1585 | case 0x10: /* DELTA-N */ | ||
1586 | case 0x11: /* DELTA-N */ | ||
1587 | case 0x12: /* ADPCM volume */ | ||
1588 | if(OPL->type&OPL_TYPE_ADPCM) | ||
1589 | YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v); | ||
1590 | break; | ||
1591 | |||
1592 | case 0x15: /* DAC data high 8 bits (F7,F6...F2) */ | ||
1593 | case 0x16: /* DAC data low 2 bits (F1, F0 in bits 7,6) */ | ||
1594 | case 0x17: /* DAC data shift (S2,S1,S0 in bits 2,1,0) */ | ||
1595 | //OPL->device->logerror("FMOPL.C: DAC data register written, but not implemented reg=%02x val=%02x\n",r,v); | ||
1596 | break; | ||
1597 | |||
1598 | case 0x18: /* I/O CTRL (Direction) */ | ||
1599 | if(OPL->type&OPL_TYPE_IO) | ||
1600 | OPL->portDirection = v&0x0f; | ||
1601 | break; | ||
1602 | case 0x19: /* I/O DATA */ | ||
1603 | if(OPL->type&OPL_TYPE_IO) | ||
1604 | { | ||
1605 | OPL->portLatch = v; | ||
1606 | if(OPL->porthandler_w) | ||
1607 | OPL->porthandler_w(OPL->port_param,v&OPL->portDirection); | ||
1608 | } | ||
1609 | break; | ||
1610 | #endif | ||
1611 | default: | ||
1612 | //OPL->device->logerror("FMOPL.C: write to unknown register: %02x\n",r); | ||
1613 | break; | ||
1614 | } | ||
1615 | break; | ||
1616 | case 0x20: /* am ON, vib ON, ksr, eg_type, mul */ | ||
1617 | slot = slot_array[r&0x1f]; | ||
1618 | if(slot < 0) return; | ||
1619 | set_mul(OPL,slot,v); | ||
1620 | break; | ||
1621 | case 0x40: | ||
1622 | slot = slot_array[r&0x1f]; | ||
1623 | if(slot < 0) return; | ||
1624 | set_ksl_tl(OPL,slot,v); | ||
1625 | break; | ||
1626 | case 0x60: | ||
1627 | slot = slot_array[r&0x1f]; | ||
1628 | if(slot < 0) return; | ||
1629 | set_ar_dr(OPL,slot,v); | ||
1630 | break; | ||
1631 | case 0x80: | ||
1632 | slot = slot_array[r&0x1f]; | ||
1633 | if(slot < 0) return; | ||
1634 | set_sl_rr(OPL,slot,v); | ||
1635 | break; | ||
1636 | case 0xa0: | ||
1637 | if (r == 0xbd) /* am depth, vibrato depth, r,bd,sd,tom,tc,hh */ | ||
1638 | { | ||
1639 | OPL->lfo_am_depth = v & 0x80; | ||
1640 | OPL->lfo_pm_depth_range = (v&0x40) ? 8 : 0; | ||
1641 | |||
1642 | OPL->rhythm = v&0x3f; | ||
1643 | |||
1644 | if(OPL->rhythm&0x20) | ||
1645 | { | ||
1646 | /* BD key on/off */ | ||
1647 | if(v&0x10) | ||
1648 | { | ||
1649 | FM_KEYON (&OPL->P_CH[6].SLOT[SLOT1], 2); | ||
1650 | FM_KEYON (&OPL->P_CH[6].SLOT[SLOT2], 2); | ||
1651 | } | ||
1652 | else | ||
1653 | { | ||
1654 | FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2); | ||
1655 | FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2); | ||
1656 | } | ||
1657 | /* HH key on/off */ | ||
1658 | if(v&0x01) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT1], 2); | ||
1659 | else FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2); | ||
1660 | /* SD key on/off */ | ||
1661 | if(v&0x08) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT2], 2); | ||
1662 | else FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2); | ||
1663 | /* TOM key on/off */ | ||
1664 | if(v&0x04) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT1], 2); | ||
1665 | else FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2); | ||
1666 | /* TOP-CY key on/off */ | ||
1667 | if(v&0x02) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT2], 2); | ||
1668 | else FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2); | ||
1669 | } | ||
1670 | else | ||
1671 | { | ||
1672 | /* BD key off */ | ||
1673 | FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2); | ||
1674 | FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2); | ||
1675 | /* HH key off */ | ||
1676 | FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2); | ||
1677 | /* SD key off */ | ||
1678 | FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2); | ||
1679 | /* TOM key off */ | ||
1680 | FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2); | ||
1681 | /* TOP-CY off */ | ||
1682 | FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2); | ||
1683 | } | ||
1684 | return; | ||
1685 | } | ||
1686 | /* keyon,block,fnum */ | ||
1687 | if( (r&0x0f) > 8) return; | ||
1688 | CH = &OPL->P_CH[r&0x0f]; | ||
1689 | if(!(r&0x10)) | ||
1690 | { /* a0-a8 */ | ||
1691 | block_fnum = (CH->block_fnum&0x1f00) | v; | ||
1692 | } | ||
1693 | else | ||
1694 | { /* b0-b8 */ | ||
1695 | block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff); | ||
1696 | |||
1697 | if(v&0x20) | ||
1698 | { | ||
1699 | FM_KEYON (&CH->SLOT[SLOT1], 1); | ||
1700 | FM_KEYON (&CH->SLOT[SLOT2], 1); | ||
1701 | } | ||
1702 | else | ||
1703 | { | ||
1704 | FM_KEYOFF(&CH->SLOT[SLOT1],~1); | ||
1705 | FM_KEYOFF(&CH->SLOT[SLOT2],~1); | ||
1706 | } | ||
1707 | } | ||
1708 | /* update */ | ||
1709 | if(CH->block_fnum != (UINT32) block_fnum) | ||
1710 | { | ||
1711 | UINT8 block = block_fnum >> 10; | ||
1712 | |||
1713 | CH->block_fnum = block_fnum; | ||
1714 | |||
1715 | CH->ksl_base = (UINT32)(ksl_tab[block_fnum>>6]); | ||
1716 | CH->fc = OPL->fn_tab[block_fnum&0x03ff] >> (7-block); | ||
1717 | |||
1718 | /* BLK 2,1,0 bits -> bits 3,2,1 of kcode */ | ||
1719 | CH->kcode = (CH->block_fnum&0x1c00)>>9; | ||
1720 | |||
1721 | /* the info below is actually opposite to what is stated in the Manuals (verifed on real YM3812) */ | ||
1722 | /* if notesel == 0 -> lsb of kcode is bit 10 (MSB) of fnum */ | ||
1723 | /* if notesel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum */ | ||
1724 | if (OPL->mode&0x40) | ||
1725 | CH->kcode |= (CH->block_fnum&0x100)>>8; /* notesel == 1 */ | ||
1726 | else | ||
1727 | CH->kcode |= (CH->block_fnum&0x200)>>9; /* notesel == 0 */ | ||
1728 | |||
1729 | /* refresh Total Level in both SLOTs of this channel */ | ||
1730 | CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl); | ||
1731 | CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl); | ||
1732 | |||
1733 | /* refresh frequency counter in both SLOTs of this channel */ | ||
1734 | CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); | ||
1735 | CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); | ||
1736 | } | ||
1737 | break; | ||
1738 | case 0xc0: | ||
1739 | /* FB,C */ | ||
1740 | if( (r&0x0f) > 8) return; | ||
1741 | CH = &OPL->P_CH[r&0x0f]; | ||
1742 | CH->SLOT[SLOT1].FB = (v>>1)&7 ? ((v>>1)&7) + 7 : 0; | ||
1743 | CH->SLOT[SLOT1].CON = v&1; | ||
1744 | CH->SLOT[SLOT1].connect1 = CH->SLOT[SLOT1].CON ? &OPL->output[0] : &OPL->phase_modulation; | ||
1745 | break; | ||
1746 | case 0xe0: /* waveform select */ | ||
1747 | /* simply ignore write to the waveform select register if selecting not enabled in test register */ | ||
1748 | if(OPL->wavesel) | ||
1749 | { | ||
1750 | slot = slot_array[r&0x1f]; | ||
1751 | if(slot < 0) return; | ||
1752 | CH = &OPL->P_CH[slot/2]; | ||
1753 | |||
1754 | CH->SLOT[slot&1].wavetable = (v&0x03)*SIN_LEN; | ||
1755 | } | ||
1756 | break; | ||
1757 | } | ||
1758 | } | ||
1759 | |||
1760 | static TIMER_CALLBACK( cymfile_callback ) | ||
1761 | { | ||
1762 | if (cymfile) | ||
1763 | { | ||
1764 | //fputc( (unsigned char)0, cymfile ); | ||
1765 | } | ||
1766 | } | ||
1767 | |||
1768 | /* lock/unlock for common table */ | ||
1769 | static int OPL_LockTable(device_t *device) | ||
1770 | { | ||
1771 | num_lock++; | ||
1772 | if(num_lock>1) return 0; | ||
1773 | |||
1774 | /* first time */ | ||
1775 | |||
1776 | /* allocate total level table (128kb space) */ | ||
1777 | if( !init_tables() ) | ||
1778 | { | ||
1779 | num_lock--; | ||
1780 | return -1; | ||
1781 | } | ||
1782 | |||
1783 | if (LOG_CYM_FILE) | ||
1784 | { | ||
1785 | cymfile = fopen("/3812_.cym","w"); | ||
1786 | if (cymfile) | ||
1787 | { | ||
1788 | //device->machine().scheduler().timer_pulse ( double::from_hz(110), FUNC(cymfile_callback)); /*110 Hz pulse timer*/ | ||
1789 | } | ||
1790 | else | ||
1791 | { | ||
1792 | //device->logerror("Could not create file 3812_.cym\n"); | ||
1793 | } | ||
1794 | } | ||
1795 | |||
1796 | return 0; | ||
1797 | } | ||
1798 | |||
1799 | static void OPL_UnLockTable(void) | ||
1800 | { | ||
1801 | if(num_lock) num_lock--; | ||
1802 | if(num_lock) return; | ||
1803 | |||
1804 | /* last time */ | ||
1805 | |||
1806 | OPLCloseTable(); | ||
1807 | |||
1808 | if (cymfile) | ||
1809 | fclose (cymfile); | ||
1810 | cymfile = NULL; | ||
1811 | } | ||
1812 | |||
1813 | static void OPLResetChip(FM_OPL *OPL) | ||
1814 | { | ||
1815 | int c,s; | ||
1816 | int i; | ||
1817 | |||
1818 | OPL->eg_timer = 0; | ||
1819 | OPL->eg_cnt = 0; | ||
1820 | |||
1821 | OPL->noise_rng = 1; /* noise shift register */ | ||
1822 | OPL->mode = 0; /* normal mode */ | ||
1823 | OPL_STATUS_RESET(OPL,0x7f); | ||
1824 | |||
1825 | /* reset with register write */ | ||
1826 | OPLWriteReg(OPL,0x01,0); /* wavesel disable */ | ||
1827 | OPLWriteReg(OPL,0x02,0); /* Timer1 */ | ||
1828 | OPLWriteReg(OPL,0x03,0); /* Timer2 */ | ||
1829 | OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */ | ||
1830 | for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0); | ||
1831 | |||
1832 | /* reset operator parameters */ | ||
1833 | for( c = 0 ; c < 9 ; c++ ) | ||
1834 | { | ||
1835 | OPL_CH *CH = &OPL->P_CH[c]; | ||
1836 | for(s = 0 ; s < 2 ; s++ ) | ||
1837 | { | ||
1838 | /* wave table */ | ||
1839 | CH->SLOT[s].wavetable = 0; | ||
1840 | CH->SLOT[s].state = EG_OFF; | ||
1841 | CH->SLOT[s].volume = MAX_ATT_INDEX; | ||
1842 | } | ||
1843 | } | ||
1844 | #if BUILD_Y8950 | ||
1845 | if(OPL->type&OPL_TYPE_ADPCM) | ||
1846 | { | ||
1847 | YM_DELTAT *DELTAT = OPL->deltat; | ||
1848 | |||
1849 | DELTAT->freqbase = OPL->freqbase; | ||
1850 | DELTAT->output_pointer = &OPL->output_deltat[0]; | ||
1851 | DELTAT->portshift = 5; | ||
1852 | DELTAT->output_range = 1<<23; | ||
1853 | YM_DELTAT_ADPCM_Reset(DELTAT,0,YM_DELTAT_EMULATION_MODE_NORMAL,OPL->device); | ||
1854 | } | ||
1855 | #endif | ||
1856 | } | ||
1857 | |||
1858 | |||
1859 | static void OPL_postload(FM_OPL *OPL) | ||
1860 | { | ||
1861 | int slot, ch; | ||
1862 | |||
1863 | for( ch=0 ; ch < 9 ; ch++ ) | ||
1864 | { | ||
1865 | OPL_CH *CH = &OPL->P_CH[ch]; | ||
1866 | |||
1867 | /* Look up key scale level */ | ||
1868 | UINT32 block_fnum = CH->block_fnum; | ||
1869 | CH->ksl_base = (UINT32)(ksl_tab[block_fnum >> 6]); | ||
1870 | CH->fc = OPL->fn_tab[block_fnum & 0x03ff] >> (7 - (block_fnum >> 10)); | ||
1871 | |||
1872 | for( slot=0 ; slot < 2 ; slot++ ) | ||
1873 | { | ||
1874 | OPL_SLOT *SLOT = &CH->SLOT[slot]; | ||
1875 | |||
1876 | /* Calculate key scale rate */ | ||
1877 | SLOT->ksr = CH->kcode >> SLOT->KSR; | ||
1878 | |||
1879 | /* Calculate attack, decay and release rates */ | ||
1880 | if ((SLOT->ar + SLOT->ksr) < 16+62) | ||
1881 | { | ||
1882 | SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; | ||
1883 | SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; | ||
1884 | } | ||
1885 | else | ||
1886 | { | ||
1887 | SLOT->eg_sh_ar = 0; | ||
1888 | SLOT->eg_sel_ar = 13*RATE_STEPS; | ||
1889 | } | ||
1890 | SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ]; | ||
1891 | SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ]; | ||
1892 | SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ]; | ||
1893 | SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ]; | ||
1894 | |||
1895 | /* Calculate phase increment */ | ||
1896 | SLOT->Incr = CH->fc * SLOT->mul; | ||
1897 | |||
1898 | /* Total level */ | ||
1899 | SLOT->TLL = SLOT->TL + (CH->ksl_base >> SLOT->ksl); | ||
1900 | |||
1901 | /* Connect output */ | ||
1902 | SLOT->connect1 = SLOT->CON ? &OPL->output[0] : &OPL->phase_modulation; | ||
1903 | } | ||
1904 | } | ||
1905 | #if BUILD_Y8950 | ||
1906 | if ( (OPL->type & OPL_TYPE_ADPCM) && (OPL->deltat) ) | ||
1907 | { | ||
1908 | // We really should call the postlod function for the YM_DELTAT, but it's hard without registers | ||
1909 | // (see the way the YM2610 does it) | ||
1910 | //YM_DELTAT_postload(OPL->deltat, REGS); | ||
1911 | } | ||
1912 | #endif | ||
1913 | } | ||
1914 | |||
1915 | |||
1916 | static void OPLsave_state_channel(device_t *device, OPL_CH *CH) | ||
1917 | { | ||
1918 | } | ||
1919 | |||
1920 | |||
1921 | /* Register savestate for a virtual YM3812/YM3526Y8950 */ | ||
1922 | |||
1923 | static void OPL_save_state(FM_OPL *OPL, device_t *device) | ||
1924 | { | ||
1925 | } | ||
1926 | |||
1927 | |||
1928 | /* Create one of virtual YM3812/YM3526/Y8950 */ | ||
1929 | /* 'clock' is chip clock in Hz */ | ||
1930 | /* 'rate' is sampling rate */ | ||
1931 | static FM_OPL *OPLCreate(device_t *device, UINT32 clock, UINT32 rate, int type) | ||
1932 | { | ||
1933 | char *ptr; | ||
1934 | FM_OPL *OPL; | ||
1935 | int state_size; | ||
1936 | |||
1937 | if (OPL_LockTable(device) == -1) return NULL; | ||
1938 | |||
1939 | /* calculate OPL state size */ | ||
1940 | state_size = sizeof(FM_OPL); | ||
1941 | |||
1942 | #if BUILD_Y8950 | ||
1943 | if (type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT); | ||
1944 | #endif | ||
1945 | |||
1946 | /* allocate memory block */ | ||
1947 | ptr = malloc(state_size); | ||
1948 | |||
1949 | if(!ptr) | ||
1950 | return NULL; | ||
1951 | |||
1952 | memset(ptr, 0, state_size); | ||
1953 | |||
1954 | OPL = (FM_OPL *)ptr; | ||
1955 | |||
1956 | /* GCC behaves weirdly... check that it's not acting up */ | ||
1957 | |||
1958 | if((UINT32)OPL & 3 == 0) | ||
1959 | printf("OPL is word-aligned"); | ||
1960 | if((UINT32)(OPL->output) & 3 == 0) | ||
1961 | printf("output is word-aligned"); | ||
1962 | |||
1963 | ptr += sizeof(FM_OPL); | ||
1964 | |||
1965 | #if BUILD_Y8950 | ||
1966 | if (type&OPL_TYPE_ADPCM) | ||
1967 | { | ||
1968 | OPL->deltat = (YM_DELTAT *)ptr; | ||
1969 | } | ||
1970 | ptr += sizeof(YM_DELTAT); | ||
1971 | #endif | ||
1972 | |||
1973 | OPL->device = device; | ||
1974 | OPL->type = type; | ||
1975 | OPL->clock = clock; | ||
1976 | OPL->rate = rate; | ||
1977 | |||
1978 | /* init global tables */ | ||
1979 | OPL_initalize(OPL); | ||
1980 | |||
1981 | return OPL; | ||
1982 | } | ||
1983 | |||
1984 | /* Destroy one of virtual YM3812 */ | ||
1985 | static void OPLDestroy(FM_OPL *OPL) | ||
1986 | { | ||
1987 | OPL_UnLockTable(); | ||
1988 | free(OPL); | ||
1989 | } | ||
1990 | |||
1991 | /* Optional handlers */ | ||
1992 | |||
1993 | static void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER timer_handler,void *param) | ||
1994 | { | ||
1995 | OPL->timer_handler = timer_handler; | ||
1996 | OPL->TimerParam = param; | ||
1997 | } | ||
1998 | static void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,void *param) | ||
1999 | { | ||
2000 | OPL->IRQHandler = IRQHandler; | ||
2001 | OPL->IRQParam = param; | ||
2002 | } | ||
2003 | static void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,void *param) | ||
2004 | { | ||
2005 | OPL->UpdateHandler = UpdateHandler; | ||
2006 | OPL->UpdateParam = param; | ||
2007 | } | ||
2008 | |||
2009 | static int OPLWrite(FM_OPL *OPL,int a,int v) | ||
2010 | { | ||
2011 | if( !(a&1) ) | ||
2012 | { /* address port */ | ||
2013 | OPL->address = v & 0xff; | ||
2014 | } | ||
2015 | else | ||
2016 | { /* data port */ | ||
2017 | if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); | ||
2018 | OPLWriteReg(OPL,OPL->address,v); | ||
2019 | } | ||
2020 | return OPL->status>>7; | ||
2021 | } | ||
2022 | |||
2023 | static unsigned char OPLRead(FM_OPL *OPL,int a) | ||
2024 | { | ||
2025 | if( !(a&1) ) | ||
2026 | { | ||
2027 | /* status port */ | ||
2028 | |||
2029 | #if BUILD_Y8950 | ||
2030 | |||
2031 | if(OPL->type&OPL_TYPE_ADPCM) /* Y8950 */ | ||
2032 | { | ||
2033 | return (OPL->status & (OPL->statusmask|0x80)) | (OPL->deltat->PCM_BSY&1); | ||
2034 | } | ||
2035 | |||
2036 | #endif | ||
2037 | |||
2038 | /* OPL and OPL2 */ | ||
2039 | return OPL->status & (OPL->statusmask|0x80); | ||
2040 | } | ||
2041 | |||
2042 | #if BUILD_Y8950 | ||
2043 | /* data port */ | ||
2044 | switch(OPL->address) | ||
2045 | { | ||
2046 | case 0x05: /* KeyBoard IN */ | ||
2047 | if(OPL->type&OPL_TYPE_KEYBOARD) | ||
2048 | { | ||
2049 | if(OPL->keyboardhandler_r) | ||
2050 | return OPL->keyboardhandler_r(OPL->keyboard_param); | ||
2051 | else | ||
2052 | OPL->device->logerror("Y8950: read unmapped KEYBOARD port\n"); | ||
2053 | } | ||
2054 | return 0; | ||
2055 | |||
2056 | case 0x0f: /* ADPCM-DATA */ | ||
2057 | if(OPL->type&OPL_TYPE_ADPCM) | ||
2058 | { | ||
2059 | UINT8 val; | ||
2060 | |||
2061 | val = YM_DELTAT_ADPCM_Read(OPL->deltat); | ||
2062 | /*logerror("Y8950: read ADPCM value read=%02x\n",val);*/ | ||
2063 | return val; | ||
2064 | } | ||
2065 | return 0; | ||
2066 | |||
2067 | case 0x19: /* I/O DATA */ | ||
2068 | if(OPL->type&OPL_TYPE_IO) | ||
2069 | { | ||
2070 | if(OPL->porthandler_r) | ||
2071 | return OPL->porthandler_r(OPL->port_param); | ||
2072 | else | ||
2073 | OPL->device->logerror("Y8950:read unmapped I/O port\n"); | ||
2074 | } | ||
2075 | return 0; | ||
2076 | case 0x1a: /* PCM-DATA */ | ||
2077 | if(OPL->type&OPL_TYPE_ADPCM) | ||
2078 | { | ||
2079 | OPL->device->logerror("Y8950 A/D convertion is accessed but not implemented !\n"); | ||
2080 | return 0x80; /* 2's complement PCM data - result from A/D convertion */ | ||
2081 | } | ||
2082 | return 0; | ||
2083 | } | ||
2084 | #endif | ||
2085 | |||
2086 | return 0xff; | ||
2087 | } | ||
2088 | |||
2089 | /* CSM Key Controll */ | ||
2090 | static void CSMKeyControll(OPL_CH *CH) | ||
2091 | { | ||
2092 | FM_KEYON (&CH->SLOT[SLOT1], 4); | ||
2093 | FM_KEYON (&CH->SLOT[SLOT2], 4); | ||
2094 | |||
2095 | /* The key off should happen exactly one sample later - not implemented correctly yet */ | ||
2096 | |||
2097 | FM_KEYOFF(&CH->SLOT[SLOT1], ~4); | ||
2098 | FM_KEYOFF(&CH->SLOT[SLOT2], ~4); | ||
2099 | } | ||
2100 | |||
2101 | |||
2102 | static int OPLTimerOver(FM_OPL *OPL,int c) | ||
2103 | { | ||
2104 | if( c ) | ||
2105 | { /* Timer B */ | ||
2106 | OPL_STATUS_SET(OPL,0x20); | ||
2107 | } | ||
2108 | else | ||
2109 | { /* Timer A */ | ||
2110 | OPL_STATUS_SET(OPL,0x40); | ||
2111 | /* CSM mode key,TL controll */ | ||
2112 | if( OPL->mode & 0x80 ) | ||
2113 | { /* CSM mode total level latch and auto key on */ | ||
2114 | int ch; | ||
2115 | if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); | ||
2116 | for(ch=0; ch<9; ch++) | ||
2117 | CSMKeyControll( &OPL->P_CH[ch] ); | ||
2118 | } | ||
2119 | } | ||
2120 | /* reload timer */ | ||
2121 | if (OPL->timer_handler) (OPL->timer_handler)(c,OPL->TimerBase * OPL->T[c]); | ||
2122 | return OPL->status>>7; | ||
2123 | } | ||
2124 | |||
2125 | |||
2126 | #define MAX_OPL_CHIPS 2 | ||
2127 | |||
2128 | |||
2129 | #if (BUILD_YM3812) | ||
2130 | |||
2131 | void * YM3812Init(device_t *device, UINT32 clock, UINT32 rate) | ||
2132 | { | ||
2133 | /* emulator create */ | ||
2134 | FM_OPL *YM3812 = OPLCreate(device,clock,rate,OPL_TYPE_YM3812); | ||
2135 | if (YM3812) | ||
2136 | { | ||
2137 | OPL_save_state(YM3812, device); | ||
2138 | YM3812ResetChip(YM3812); | ||
2139 | } | ||
2140 | return YM3812; | ||
2141 | } | ||
2142 | |||
2143 | void YM3812Shutdown(void *chip) | ||
2144 | { | ||
2145 | FM_OPL *YM3812 = (FM_OPL *)chip; | ||
2146 | |||
2147 | /* emulator shutdown */ | ||
2148 | OPLDestroy(YM3812); | ||
2149 | } | ||
2150 | void YM3812ResetChip(void *chip) | ||
2151 | { | ||
2152 | FM_OPL *YM3812 = (FM_OPL *)chip; | ||
2153 | OPLResetChip(YM3812); | ||
2154 | } | ||
2155 | |||
2156 | int YM3812Write(void *chip, int a, int v) | ||
2157 | { | ||
2158 | FM_OPL *YM3812 = (FM_OPL *)chip; | ||
2159 | |||
2160 | OPLWriteReg(YM3812, a, v); | ||
2161 | return (YM3812->status>>7); | ||
2162 | |||
2163 | // technically correct, but breaks Wolf4SDL - FW19 | ||
2164 | //return OPLWrite(YM3812, a, v); | ||
2165 | } | ||
2166 | |||
2167 | unsigned char YM3812Read(void *chip, int a) | ||
2168 | { | ||
2169 | FM_OPL *YM3812 = (FM_OPL *)chip; | ||
2170 | /* YM3812 always returns bit2 and bit1 in HIGH state */ | ||
2171 | return OPLRead(YM3812, a) | 0x06 ; | ||
2172 | } | ||
2173 | int YM3812TimerOver(void *chip, int c) | ||
2174 | { | ||
2175 | FM_OPL *YM3812 = (FM_OPL *)chip; | ||
2176 | return OPLTimerOver(YM3812, c); | ||
2177 | } | ||
2178 | |||
2179 | void YM3812SetTimerHandler(void *chip, OPL_TIMERHANDLER timer_handler, void *param) | ||
2180 | { | ||
2181 | FM_OPL *YM3812 = (FM_OPL *)chip; | ||
2182 | OPLSetTimerHandler(YM3812, timer_handler, param); | ||
2183 | } | ||
2184 | void YM3812SetIRQHandler(void *chip,OPL_IRQHANDLER IRQHandler,void *param) | ||
2185 | { | ||
2186 | FM_OPL *YM3812 = (FM_OPL *)chip; | ||
2187 | OPLSetIRQHandler(YM3812, IRQHandler, param); | ||
2188 | } | ||
2189 | void YM3812SetUpdateHandler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param) | ||
2190 | { | ||
2191 | FM_OPL *YM3812 = (FM_OPL *)chip; | ||
2192 | OPLSetUpdateHandler(YM3812, UpdateHandler, param); | ||
2193 | } | ||
2194 | |||
2195 | |||
2196 | /* | ||
2197 | ** Generate samples for one of the YM3812's | ||
2198 | ** | ||
2199 | ** 'which' is the virtual YM3812 number | ||
2200 | ** '*buffer' is the output buffer pointer | ||
2201 | ** 'length' is the number of samples that should be generated | ||
2202 | */ | ||
2203 | void YM3812UpdateOne(void *chip, OPLSAMPLE *buffer, int length) | ||
2204 | { | ||
2205 | FM_OPL *OPL = (FM_OPL *)chip; | ||
2206 | UINT8 rhythm = OPL->rhythm&0x20; | ||
2207 | OPLSAMPLE *buf = buffer; | ||
2208 | int i; | ||
2209 | |||
2210 | for( i=0; i < length ; i++ ) | ||
2211 | { | ||
2212 | int lt; | ||
2213 | |||
2214 | OPL->output[0] = 0; | ||
2215 | |||
2216 | advance_lfo(OPL); | ||
2217 | |||
2218 | /* FM part */ | ||
2219 | OPL_CALC_CH(OPL, &OPL->P_CH[0]); | ||
2220 | OPL_CALC_CH(OPL, &OPL->P_CH[1]); | ||
2221 | OPL_CALC_CH(OPL, &OPL->P_CH[2]); | ||
2222 | OPL_CALC_CH(OPL, &OPL->P_CH[3]); | ||
2223 | OPL_CALC_CH(OPL, &OPL->P_CH[4]); | ||
2224 | OPL_CALC_CH(OPL, &OPL->P_CH[5]); | ||
2225 | |||
2226 | if(!rhythm) | ||
2227 | { | ||
2228 | OPL_CALC_CH(OPL, &OPL->P_CH[6]); | ||
2229 | OPL_CALC_CH(OPL, &OPL->P_CH[7]); | ||
2230 | OPL_CALC_CH(OPL, &OPL->P_CH[8]); | ||
2231 | } | ||
2232 | else /* Rhythm part */ | ||
2233 | { | ||
2234 | OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 ); | ||
2235 | } | ||
2236 | |||
2237 | lt = OPL->output[0]; | ||
2238 | |||
2239 | //lt >>= FINAL_SH; | ||
2240 | lt <<= 2; | ||
2241 | |||
2242 | /* limit check */ | ||
2243 | lt = limit( lt , MAXOUT, MINOUT ); | ||
2244 | |||
2245 | #ifdef SAVE_SAMPLE | ||
2246 | if (which==0) | ||
2247 | { | ||
2248 | SAVE_ALL_CHANNELS | ||
2249 | } | ||
2250 | #endif | ||
2251 | |||
2252 | /* store to sound buffer */ | ||
2253 | //buf[i] = lt; | ||
2254 | |||
2255 | buf[i*2] = lt; // stereo version | ||
2256 | buf[i*2+1] = lt; | ||
2257 | |||
2258 | advance(OPL); | ||
2259 | } | ||
2260 | } | ||
2261 | #endif /* BUILD_YM3812 */ | ||
2262 | |||
2263 | // Rockbox: we don't care about the rest. | ||
2264 | |||
2265 | #if (BUILD_YM3526) | ||
2266 | |||
2267 | void *ym3526_init(device_t *device, UINT32 clock, UINT32 rate) | ||
2268 | { | ||
2269 | /* emulator create */ | ||
2270 | FM_OPL *YM3526 = OPLCreate(device,clock,rate,OPL_TYPE_YM3526); | ||
2271 | if (YM3526) | ||
2272 | { | ||
2273 | OPL_save_state(YM3526, device); | ||
2274 | ym3526_reset_chip(YM3526); | ||
2275 | } | ||
2276 | return YM3526; | ||
2277 | } | ||
2278 | |||
2279 | void ym3526_shutdown(void *chip) | ||
2280 | { | ||
2281 | FM_OPL *YM3526 = (FM_OPL *)chip; | ||
2282 | /* emulator shutdown */ | ||
2283 | OPLDestroy(YM3526); | ||
2284 | } | ||
2285 | void ym3526_reset_chip(void *chip) | ||
2286 | { | ||
2287 | FM_OPL *YM3526 = (FM_OPL *)chip; | ||
2288 | OPLResetChip(YM3526); | ||
2289 | } | ||
2290 | |||
2291 | int ym3526_write(void *chip, int a, int v) | ||
2292 | { | ||
2293 | FM_OPL *YM3526 = (FM_OPL *)chip; | ||
2294 | return OPLWrite(YM3526, a, v); | ||
2295 | } | ||
2296 | |||
2297 | unsigned char ym3526_read(void *chip, int a) | ||
2298 | { | ||
2299 | FM_OPL *YM3526 = (FM_OPL *)chip; | ||
2300 | /* YM3526 always returns bit2 and bit1 in HIGH state */ | ||
2301 | return OPLRead(YM3526, a) | 0x06 ; | ||
2302 | } | ||
2303 | int ym3526_timer_over(void *chip, int c) | ||
2304 | { | ||
2305 | FM_OPL *YM3526 = (FM_OPL *)chip; | ||
2306 | return OPLTimerOver(YM3526, c); | ||
2307 | } | ||
2308 | |||
2309 | void ym3526_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param) | ||
2310 | { | ||
2311 | FM_OPL *YM3526 = (FM_OPL *)chip; | ||
2312 | OPLSetTimerHandler(YM3526, timer_handler, param); | ||
2313 | } | ||
2314 | void ym3526_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param) | ||
2315 | { | ||
2316 | FM_OPL *YM3526 = (FM_OPL *)chip; | ||
2317 | OPLSetIRQHandler(YM3526, IRQHandler, param); | ||
2318 | } | ||
2319 | void ym3526_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param) | ||
2320 | { | ||
2321 | FM_OPL *YM3526 = (FM_OPL *)chip; | ||
2322 | OPLSetUpdateHandler(YM3526, UpdateHandler, param); | ||
2323 | } | ||
2324 | |||
2325 | |||
2326 | /* | ||
2327 | ** Generate samples for one of the YM3526's | ||
2328 | ** | ||
2329 | ** 'which' is the virtual YM3526 number | ||
2330 | ** '*buffer' is the output buffer pointer | ||
2331 | ** 'length' is the number of samples that should be generated | ||
2332 | */ | ||
2333 | void ym3526_update_one(void *chip, OPLSAMPLE *buffer, int length) | ||
2334 | { | ||
2335 | FM_OPL *OPL = (FM_OPL *)chip; | ||
2336 | UINT8 rhythm = OPL->rhythm&0x20; | ||
2337 | OPLSAMPLE *buf = buffer; | ||
2338 | int i; | ||
2339 | |||
2340 | for( i=0; i < length ; i++ ) | ||
2341 | { | ||
2342 | int lt; | ||
2343 | |||
2344 | OPL->output[0] = 0; | ||
2345 | |||
2346 | advance_lfo(OPL); | ||
2347 | |||
2348 | /* FM part */ | ||
2349 | OPL_CALC_CH(OPL, &OPL->P_CH[0]); | ||
2350 | OPL_CALC_CH(OPL, &OPL->P_CH[1]); | ||
2351 | OPL_CALC_CH(OPL, &OPL->P_CH[2]); | ||
2352 | OPL_CALC_CH(OPL, &OPL->P_CH[3]); | ||
2353 | OPL_CALC_CH(OPL, &OPL->P_CH[4]); | ||
2354 | OPL_CALC_CH(OPL, &OPL->P_CH[5]); | ||
2355 | |||
2356 | if(!rhythm) | ||
2357 | { | ||
2358 | OPL_CALC_CH(OPL, &OPL->P_CH[6]); | ||
2359 | OPL_CALC_CH(OPL, &OPL->P_CH[7]); | ||
2360 | OPL_CALC_CH(OPL, &OPL->P_CH[8]); | ||
2361 | } | ||
2362 | else /* Rhythm part */ | ||
2363 | { | ||
2364 | OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 ); | ||
2365 | } | ||
2366 | |||
2367 | lt = OPL->output[0]; | ||
2368 | |||
2369 | lt >>= FINAL_SH; | ||
2370 | |||
2371 | /* limit check */ | ||
2372 | lt = limit( lt , MAXOUT, MINOUT ); | ||
2373 | |||
2374 | #ifdef SAVE_SAMPLE | ||
2375 | if (which==0) | ||
2376 | { | ||
2377 | SAVE_ALL_CHANNELS | ||
2378 | } | ||
2379 | #endif | ||
2380 | |||
2381 | /* store to sound buffer */ | ||
2382 | buf[i] = lt; | ||
2383 | |||
2384 | advance(OPL); | ||
2385 | } | ||
2386 | |||
2387 | } | ||
2388 | #endif /* BUILD_YM3526 */ | ||
2389 | |||
2390 | |||
2391 | |||
2392 | |||
2393 | #if BUILD_Y8950 | ||
2394 | |||
2395 | static void Y8950_deltat_status_set(void *chip, UINT8 changebits) | ||
2396 | { | ||
2397 | FM_OPL *Y8950 = (FM_OPL *)chip; | ||
2398 | OPL_STATUS_SET(Y8950, changebits); | ||
2399 | } | ||
2400 | static void Y8950_deltat_status_reset(void *chip, UINT8 changebits) | ||
2401 | { | ||
2402 | FM_OPL *Y8950 = (FM_OPL *)chip; | ||
2403 | OPL_STATUS_RESET(Y8950, changebits); | ||
2404 | } | ||
2405 | |||
2406 | void *y8950_init(device_t *device, UINT32 clock, UINT32 rate) | ||
2407 | { | ||
2408 | /* emulator create */ | ||
2409 | FM_OPL *Y8950 = OPLCreate(device,clock,rate,OPL_TYPE_Y8950); | ||
2410 | if (Y8950) | ||
2411 | { | ||
2412 | Y8950->deltat->status_set_handler = Y8950_deltat_status_set; | ||
2413 | Y8950->deltat->status_reset_handler = Y8950_deltat_status_reset; | ||
2414 | Y8950->deltat->status_change_which_chip = Y8950; | ||
2415 | Y8950->deltat->status_change_EOS_bit = 0x10; /* status flag: set bit4 on End Of Sample */ | ||
2416 | Y8950->deltat->status_change_BRDY_bit = 0x08; /* status flag: set bit3 on BRDY (End Of: ADPCM analysis/synthesis, memory reading/writing) */ | ||
2417 | |||
2418 | /*Y8950->deltat->write_time = 10.0 / clock;*/ /* a single byte write takes 10 cycles of main clock */ | ||
2419 | /*Y8950->deltat->read_time = 8.0 / clock;*/ /* a single byte read takes 8 cycles of main clock */ | ||
2420 | /* reset */ | ||
2421 | OPL_save_state(Y8950, device); | ||
2422 | y8950_reset_chip(Y8950); | ||
2423 | } | ||
2424 | |||
2425 | return Y8950; | ||
2426 | } | ||
2427 | |||
2428 | void y8950_shutdown(void *chip) | ||
2429 | { | ||
2430 | FM_OPL *Y8950 = (FM_OPL *)chip; | ||
2431 | /* emulator shutdown */ | ||
2432 | OPLDestroy(Y8950); | ||
2433 | } | ||
2434 | void y8950_reset_chip(void *chip) | ||
2435 | { | ||
2436 | FM_OPL *Y8950 = (FM_OPL *)chip; | ||
2437 | OPLResetChip(Y8950); | ||
2438 | } | ||
2439 | |||
2440 | int y8950_write(void *chip, int a, int v) | ||
2441 | { | ||
2442 | FM_OPL *Y8950 = (FM_OPL *)chip; | ||
2443 | return OPLWrite(Y8950, a, v); | ||
2444 | } | ||
2445 | |||
2446 | unsigned char y8950_read(void *chip, int a) | ||
2447 | { | ||
2448 | FM_OPL *Y8950 = (FM_OPL *)chip; | ||
2449 | return OPLRead(Y8950, a); | ||
2450 | } | ||
2451 | int y8950_timer_over(void *chip, int c) | ||
2452 | { | ||
2453 | FM_OPL *Y8950 = (FM_OPL *)chip; | ||
2454 | return OPLTimerOver(Y8950, c); | ||
2455 | } | ||
2456 | |||
2457 | void y8950_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param) | ||
2458 | { | ||
2459 | FM_OPL *Y8950 = (FM_OPL *)chip; | ||
2460 | OPLSetTimerHandler(Y8950, timer_handler, param); | ||
2461 | } | ||
2462 | void y8950_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param) | ||
2463 | { | ||
2464 | FM_OPL *Y8950 = (FM_OPL *)chip; | ||
2465 | OPLSetIRQHandler(Y8950, IRQHandler, param); | ||
2466 | } | ||
2467 | void y8950_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param) | ||
2468 | { | ||
2469 | FM_OPL *Y8950 = (FM_OPL *)chip; | ||
2470 | OPLSetUpdateHandler(Y8950, UpdateHandler, param); | ||
2471 | } | ||
2472 | |||
2473 | void y8950_set_delta_t_memory(void *chip, void * deltat_mem_ptr, int deltat_mem_size ) | ||
2474 | { | ||
2475 | FM_OPL *OPL = (FM_OPL *)chip; | ||
2476 | OPL->deltat->memory = (UINT8 *)(deltat_mem_ptr); | ||
2477 | OPL->deltat->memory_size = deltat_mem_size; | ||
2478 | } | ||
2479 | |||
2480 | /* | ||
2481 | ** Generate samples for one of the Y8950's | ||
2482 | ** | ||
2483 | ** 'which' is the virtual Y8950 number | ||
2484 | ** '*buffer' is the output buffer pointer | ||
2485 | ** 'length' is the number of samples that should be generated | ||
2486 | */ | ||
2487 | void y8950_update_one(void *chip, OPLSAMPLE *buffer, int length) | ||
2488 | { | ||
2489 | int i; | ||
2490 | FM_OPL *OPL = (FM_OPL *)chip; | ||
2491 | UINT8 rhythm = OPL->rhythm&0x20; | ||
2492 | YM_DELTAT *DELTAT = OPL->deltat; | ||
2493 | OPLSAMPLE *buf = buffer; | ||
2494 | |||
2495 | for( i=0; i < length ; i++ ) | ||
2496 | { | ||
2497 | int lt; | ||
2498 | |||
2499 | OPL->output[0] = 0; | ||
2500 | OPL->output_deltat[0] = 0; | ||
2501 | |||
2502 | advance_lfo(OPL); | ||
2503 | |||
2504 | /* deltaT ADPCM */ | ||
2505 | if( DELTAT->portstate&0x80 ) | ||
2506 | YM_DELTAT_ADPCM_CALC(DELTAT); | ||
2507 | |||
2508 | /* FM part */ | ||
2509 | OPL_CALC_CH(OPL, &OPL->P_CH[0]); | ||
2510 | OPL_CALC_CH(OPL, &OPL->P_CH[1]); | ||
2511 | OPL_CALC_CH(OPL, &OPL->P_CH[2]); | ||
2512 | OPL_CALC_CH(OPL, &OPL->P_CH[3]); | ||
2513 | OPL_CALC_CH(OPL, &OPL->P_CH[4]); | ||
2514 | OPL_CALC_CH(OPL, &OPL->P_CH[5]); | ||
2515 | |||
2516 | if(!rhythm) | ||
2517 | { | ||
2518 | OPL_CALC_CH(OPL, &OPL->P_CH[6]); | ||
2519 | OPL_CALC_CH(OPL, &OPL->P_CH[7]); | ||
2520 | OPL_CALC_CH(OPL, &OPL->P_CH[8]); | ||
2521 | } | ||
2522 | else /* Rhythm part */ | ||
2523 | { | ||
2524 | OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 ); | ||
2525 | } | ||
2526 | |||
2527 | lt = OPL->output[0] + (OPL->output_deltat[0]>>11); | ||
2528 | |||
2529 | lt >>= FINAL_SH; | ||
2530 | |||
2531 | /* limit check */ | ||
2532 | lt = limit( lt , MAXOUT, MINOUT ); | ||
2533 | |||
2534 | #ifdef SAVE_SAMPLE | ||
2535 | if (which==0) | ||
2536 | { | ||
2537 | SAVE_ALL_CHANNELS | ||
2538 | } | ||
2539 | #endif | ||
2540 | |||
2541 | /* store to sound buffer */ | ||
2542 | buf[i] = lt; | ||
2543 | |||
2544 | advance(OPL); | ||
2545 | } | ||
2546 | |||
2547 | } | ||
2548 | |||
2549 | void y8950_set_port_handler(void *chip,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,void * param) | ||
2550 | { | ||
2551 | FM_OPL *OPL = (FM_OPL *)chip; | ||
2552 | OPL->porthandler_w = PortHandler_w; | ||
2553 | OPL->porthandler_r = PortHandler_r; | ||
2554 | OPL->port_param = param; | ||
2555 | } | ||
2556 | |||
2557 | void y8950_set_keyboard_handler(void *chip,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,void * param) | ||
2558 | { | ||
2559 | FM_OPL *OPL = (FM_OPL *)chip; | ||
2560 | OPL->keyboardhandler_w = KeyboardHandler_w; | ||
2561 | OPL->keyboardhandler_r = KeyboardHandler_r; | ||
2562 | OPL->keyboard_param = param; | ||
2563 | } | ||
2564 | |||
2565 | #endif | ||