1 // Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
5 /* Copyright (C) 2006-2008 Shay Green. This module is free software; you
6 can redistribute it and/or modify it under the terms of the GNU Lesser
7 General Public License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version. This
9 module is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 details. You should have received a copy of the GNU Lesser General Public
13 License along with this module; if not, write to the Free Software Foundation,
14 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
16 #include "blargg_source.h"
18 // Emulation inaccuracies:
19 // * Noise isn't run when not in use
20 // * Changes to envelope and noise periods are delayed until next reload
21 // * Super-sonic tone should attenuate output to about 60%, not 50%
23 // Tones above this frequency are treated as disabled tone at half volume.
24 // Power of two is more efficient (avoids division).
25 int const inaudible_freq
= 16384;
27 int const period_factor
= 16;
29 static byte
const amp_table
[16] =
31 #define ENTRY( n ) (byte) (n * ay_amp_range + 0.5)
32 // With channels tied together and 1K resistor to ground (as datasheet recommends),
33 // output nearly matches logarithmic curve as claimed. Approx. 1.5 dB per step.
34 ENTRY(0.000000),ENTRY(0.007813),ENTRY(0.011049),ENTRY(0.015625),
35 ENTRY(0.022097),ENTRY(0.031250),ENTRY(0.044194),ENTRY(0.062500),
36 ENTRY(0.088388),ENTRY(0.125000),ENTRY(0.176777),ENTRY(0.250000),
37 ENTRY(0.353553),ENTRY(0.500000),ENTRY(0.707107),ENTRY(1.000000),
40 // Measured from an AY-3-8910A chip with date code 8611.
42 // Direct voltages without any load (very linear)
43 ENTRY(0.000000),ENTRY(0.046237),ENTRY(0.064516),ENTRY(0.089785),
44 ENTRY(0.124731),ENTRY(0.173118),ENTRY(0.225806),ENTRY(0.329032),
45 ENTRY(0.360215),ENTRY(0.494624),ENTRY(0.594624),ENTRY(0.672043),
46 ENTRY(0.766129),ENTRY(0.841935),ENTRY(0.926882),ENTRY(1.000000),
47 // With only some load
48 ENTRY(0.000000),ENTRY(0.011940),ENTRY(0.017413),ENTRY(0.024876),
49 ENTRY(0.036318),ENTRY(0.054229),ENTRY(0.072637),ENTRY(0.122388),
50 ENTRY(0.174129),ENTRY(0.239303),ENTRY(0.323881),ENTRY(0.410945),
51 ENTRY(0.527363),ENTRY(0.651741),ENTRY(0.832338),ENTRY(1.000000),
56 static byte
const modes
[8] =
58 #define MODE( a0,a1, b0,b1, c0,c1 ) \
59 (a0 | a1<<1 | b0<<2 | b1<<3 | c0<<4 | c1<<5)
60 MODE( 1,0, 1,0, 1,0 ),
61 MODE( 1,0, 0,0, 0,0 ),
62 MODE( 1,0, 0,1, 1,0 ),
63 MODE( 1,0, 1,1, 1,1 ),
64 MODE( 0,1, 0,1, 0,1 ),
65 MODE( 0,1, 1,1, 1,1 ),
66 MODE( 0,1, 1,0, 0,1 ),
67 MODE( 0,1, 0,0, 0,0 ),
70 static void set_output( struct Ay_Apu
* this, struct Blip_Buffer
* b
)
73 for ( i
= 0; i
< ay_osc_count
; ++i
)
74 Ay_apu_set_output( this, i
, b
);
77 void Ay_apu_init( struct Ay_Apu
* this )
79 Synth_init( &this->synth_
);
81 // build full table of the upper 8 envelope waveforms
85 byte
* out
= this->env_modes
[m
];
86 int x
, y
, flags
= modes
[m
];
87 for ( x
= 3; --x
>= 0; )
90 int end
= flags
>> 1 & 1;
93 for ( y
= 16; --y
>= 0; )
95 *out
++ = amp_table
[amp
];
102 set_output( this, NULL
);
103 Ay_apu_volume( this, (int)FP_ONE_VOLUME
);
104 Ay_apu_reset( this );
107 void Ay_apu_reset( struct Ay_Apu
* this )
111 this->noise_delay
= 0;
112 this->noise_lfsr
= 1;
115 for ( osc
= &this->oscs
[ay_osc_count
]; osc
!= this->oscs
; )
118 osc
->period
= period_factor
;
125 for ( i
= sizeof this->regs
; --i
>= 0; )
127 this->regs
[7] = 0xFF;
128 write_data_( this, 13, 0 );
131 int Ay_apu_read( struct Ay_Apu
* this )
133 static byte
const masks
[ay_reg_count
] = {
134 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x1F, 0x3F,
135 0x1F, 0x1F, 0x1F, 0xFF, 0xFF, 0x0F, 0x00, 0x00
137 return this->regs
[this->addr_
] & masks
[this->addr_
];
140 void write_data_( struct Ay_Apu
* this, int addr
, int data
)
142 assert( (unsigned) addr
< ay_reg_count
);
144 /* if ( (unsigned) addr >= 14 )
145 dprintf( "Wrote to I/O port %02X\n", (int) addr ); */
150 if ( !(data
& 8) ) // convert modes 0-7 to proper equivalents
151 data
= (data
& 4) ? 15 : 9;
152 this->env_wave
= this->env_modes
[data
- 7];
154 this->env_delay
= 0; // will get set to envelope period in run_until()
156 this->regs
[addr
] = data
;
158 // handle period changes accurately
160 if ( i
< ay_osc_count
)
162 blip_time_t period
= (this->regs
[i
* 2 + 1] & 0x0F) * (0x100 * period_factor
) +
163 this->regs
[i
* 2] * period_factor
;
165 period
= period_factor
;
167 // adjust time of next timer expiration based on change in period
168 struct osc_t
* osc
= &this->oscs
[i
];
169 if ( (osc
->delay
+= period
- osc
->period
) < 0 )
171 osc
->period
= period
;
174 // TODO: same as above for envelope timer, and it also has a divide by two after it
177 int const noise_off
= 0x08;
178 int const tone_off
= 0x01;
180 void run_until( struct Ay_Apu
* this, blip_time_t final_end_time
)
182 require( final_end_time
>= this->last_time
);
184 // noise period and initial values
185 blip_time_t
const noise_period_factor
= period_factor
* 2; // verified
186 blip_time_t noise_period
= (this->regs
[6] & 0x1F) * noise_period_factor
;
188 noise_period
= noise_period_factor
;
189 blip_time_t
const old_noise_delay
= this->noise_delay
;
190 unsigned const old_noise_lfsr
= this->noise_lfsr
;
193 blip_time_t
const env_period_factor
= period_factor
* 2; // verified
194 blip_time_t env_period
= (this->regs
[12] * 0x100 + this->regs
[11]) * env_period_factor
;
196 env_period
= env_period_factor
; // same as period 1 on my AY chip
197 if ( !this->env_delay
)
198 this->env_delay
= env_period
;
200 // run each osc separately
202 for ( index
= 0; index
< ay_osc_count
; index
++ )
204 struct osc_t
* const osc
= &this->oscs
[index
];
205 int osc_mode
= this->regs
[7] >> index
;
208 struct Blip_Buffer
* const osc_output
= osc
->output
;
211 Blip_set_modified( osc_output
);
215 blip_time_t inaudible_period
= (unsigned) (Blip_clock_rate( osc_output
) +
216 inaudible_freq
) / (unsigned) (inaudible_freq
* 2);
217 if ( osc
->period
<= inaudible_period
&& !(osc_mode
& tone_off
) )
219 half_vol
= 1; // Actually around 60%, but 50% is close enough
220 osc_mode
|= tone_off
;
224 blip_time_t start_time
= this->last_time
;
225 blip_time_t end_time
= final_end_time
;
226 int const vol_mode
= this->regs
[0x08 + index
];
227 int volume
= amp_table
[vol_mode
& 0x0F] >> half_vol
;
228 int osc_env_pos
= this->env_pos
;
229 if ( vol_mode
& 0x10 )
231 volume
= this->env_wave
[osc_env_pos
] >> half_vol
;
232 // use envelope only if it's a repeating wave or a ramp that hasn't finished
233 if ( !(this->regs
[13] & 1) || osc_env_pos
< -32 )
235 end_time
= start_time
+ this->env_delay
;
236 if ( end_time
>= final_end_time
)
237 end_time
= final_end_time
;
239 //if ( !(regs [12] | regs [11]) )
240 // dprintf( "Used envelope period 0\n" );
244 osc_mode
= noise_off
| tone_off
;
249 osc_mode
= noise_off
| tone_off
;
253 blip_time_t
const period
= osc
->period
;
254 blip_time_t time
= start_time
+ osc
->delay
;
255 if ( osc_mode
& tone_off
) // maintain tone's phase when off
257 int count
= (final_end_time
- time
+ period
- 1) / period
;
258 time
+= count
* period
;
259 osc
->phase
^= count
& 1;
263 blip_time_t ntime
= final_end_time
;
264 unsigned noise_lfsr
= 1;
265 if ( !(osc_mode
& noise_off
) )
267 ntime
= start_time
+ old_noise_delay
;
268 noise_lfsr
= old_noise_lfsr
;
269 //if ( (regs [6] & 0x1F) == 0 )
270 // dprintf( "Used noise period 0\n" );
273 // The following efficiently handles several cases (least demanding first):
274 // * Tone, noise, and envelope disabled, where channel acts as 4-bit DAC
275 // * Just tone or just noise, envelope disabled
276 // * Envelope controlling tone and/or noise
277 // * Tone and noise disabled, envelope enabled with high frequency
278 // * Tone and noise together
279 // * Tone and noise together with envelope
281 // this loop only runs one iteration if envelope is disabled. If envelope
282 // is being used as a waveform (tone and noise disabled), this loop will
283 // still be reasonably efficient since the bulk of it will be skipped.
288 if ( (osc_mode
| osc
->phase
) & 1 & (osc_mode
>> 3 | noise_lfsr
) )
291 int delta
= amp
- osc
->last_amp
;
295 Synth_offset( &this->synth_
, start_time
, delta
, osc_output
);
299 // Run wave and noise interleved with each catching up to the other.
300 // If one or both are disabled, their "current time" will be past end time,
301 // so there will be no significant performance hit.
302 if ( ntime
< end_time
|| time
< end_time
)
304 // Since amplitude was updated above, delta will always be +/- volume,
305 // so we can avoid using last_amp every time to calculate the delta.
306 int delta
= amp
* 2 - volume
;
307 int delta_non_zero
= delta
!= 0;
308 int phase
= osc
->phase
| (osc_mode
& tone_off
); assert( tone_off
== 0x01 );
312 blip_time_t end
= end_time
;
313 if ( end_time
> time
) end
= time
;
314 if ( phase
& delta_non_zero
)
316 while ( ntime
<= end
) // must advance *past* time to avoid hang
318 int changed
= noise_lfsr
+ 1;
319 noise_lfsr
= (-(noise_lfsr
& 1) & 0x12000) ^ (noise_lfsr
>> 1);
323 Synth_offset( &this->synth_
, ntime
, delta
, osc_output
);
325 ntime
+= noise_period
;
330 // 20 or more noise periods on average for some music
331 int remain
= end
- ntime
;
332 int count
= remain
/ noise_period
;
334 ntime
+= noise_period
+ count
* noise_period
;
339 if ( end_time
> ntime
) end
= ntime
;
340 if ( noise_lfsr
& delta_non_zero
)
345 Synth_offset( &this->synth_
, time
, delta
, osc_output
);
348 // alternate (less-efficient) implementation
351 phase
= (unsigned) (-delta
) >> (CHAR_BIT
* sizeof (unsigned) - 1);
352 check( phase
== (delta
> 0) );
356 // loop usually runs less than once
357 //SUB_CASE_COUNTER( (time < end) * (end - time + period - 1) / period );
366 while ( time
< end_time
|| ntime
< end_time
);
368 osc
->last_amp
= (delta
+ volume
) >> 1;
369 if ( !(osc_mode
& tone_off
) )
373 if ( end_time
>= final_end_time
)
374 break; // breaks first time when envelope is disabled
376 // next envelope step
377 if ( ++osc_env_pos
>= 0 )
379 volume
= this->env_wave
[osc_env_pos
] >> half_vol
;
381 start_time
= end_time
;
382 end_time
+= env_period
;
383 if ( end_time
> final_end_time
)
384 end_time
= final_end_time
;
386 osc
->delay
= time
- final_end_time
;
388 if ( !(osc_mode
& noise_off
) )
390 this->noise_delay
= ntime
- final_end_time
;
391 this->noise_lfsr
= noise_lfsr
;
395 // TODO: optimized saw wave envelope?
397 // maintain envelope phase
398 blip_time_t remain
= final_end_time
- this->last_time
- this->env_delay
;
401 int count
= (remain
+ env_period
) / env_period
;
402 this->env_pos
+= count
;
403 if ( this->env_pos
>= 0 )
404 this->env_pos
= (this->env_pos
& 31) - 32;
405 remain
-= count
* env_period
;
406 assert( -remain
<= env_period
);
408 this->env_delay
= -remain
;
409 assert( this->env_delay
> 0 );
410 assert( this->env_pos
< 0 );
412 this->last_time
= final_end_time
;