diff options
Diffstat (limited to 'apps/codecs/libgme/nsf_emu.c')
-rw-r--r-- | apps/codecs/libgme/nsf_emu.c | 496 |
1 files changed, 154 insertions, 342 deletions
diff --git a/apps/codecs/libgme/nsf_emu.c b/apps/codecs/libgme/nsf_emu.c index a4873c81cb..705c345fa6 100644 --- a/apps/codecs/libgme/nsf_emu.c +++ b/apps/codecs/libgme/nsf_emu.c | |||
@@ -1,4 +1,4 @@ | |||
1 | // Game_Music_Emu 0.5.5. http://www.slack.net/~ant/ | 1 | // Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/ |
2 | 2 | ||
3 | #include "nsf_emu.h" | 3 | #include "nsf_emu.h" |
4 | #include "multi_buffer.h" | 4 | #include "multi_buffer.h" |
@@ -19,33 +19,19 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ | |||
19 | #include "blargg_source.h" | 19 | #include "blargg_source.h" |
20 | 20 | ||
21 | const char gme_wrong_file_type [] = "Wrong file type for this emulator"; | 21 | const char gme_wrong_file_type [] = "Wrong file type for this emulator"; |
22 | long const clock_divisor = 12; | ||
23 | |||
24 | int const stereo = 2; // number of channels for stereo | ||
25 | int const silence_max = 6; // seconds | ||
26 | int const silence_threshold = 0x10; | ||
27 | long const fade_block_size = 512; | ||
28 | int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift) | ||
29 | 22 | ||
30 | // number of frames until play interrupts init | 23 | // number of frames until play interrupts init |
31 | int const initial_play_delay = 7; // KikiKaikai needed this to work | 24 | int const initial_play_delay = 7; // KikiKaikai needed this to work |
25 | int const bank_size = 0x1000; | ||
32 | int const rom_addr = 0x8000; | 26 | int const rom_addr = 0x8000; |
33 | 27 | ||
34 | static void clear_track_vars( struct Nsf_Emu* this ) | 28 | static void clear_track_vars( struct Nsf_Emu* this ) |
35 | { | 29 | { |
36 | this->current_track = -1; | 30 | this->current_track = -1; |
37 | this->out_time = 0; | 31 | track_stop( &this->track_filter ); |
38 | this->emu_time = 0; | ||
39 | this->emu_track_ended_ = true; | ||
40 | this->track_ended = true; | ||
41 | this->fade_start = INT_MAX / 2 + 1; | ||
42 | this->fade_step = 1; | ||
43 | this->silence_time = 0; | ||
44 | this->silence_count = 0; | ||
45 | this->buf_remain = 0; | ||
46 | } | 32 | } |
47 | 33 | ||
48 | static int pcm_read( void* emu, addr_t addr ) | 34 | static int pcm_read( void* emu, int addr ) |
49 | { | 35 | { |
50 | return *Cpu_get_code( &((struct Nsf_Emu*) emu)->cpu, addr ); | 36 | return *Cpu_get_code( &((struct Nsf_Emu*) emu)->cpu, addr ); |
51 | } | 37 | } |
@@ -58,18 +44,16 @@ void Nsf_init( struct Nsf_Emu* this ) | |||
58 | this->gain = (int)(FP_ONE_GAIN); | 44 | this->gain = (int)(FP_ONE_GAIN); |
59 | 45 | ||
60 | // defaults | 46 | // defaults |
61 | this->max_initial_silence = 2; | 47 | this->tfilter = *track_get_setup( &this->track_filter ); |
62 | this->ignore_silence = false; | 48 | this->tfilter.max_initial = 2; |
63 | this->voice_count = 0; | 49 | this->tfilter.lookahead = 6; |
50 | this->track_filter.silence_ignored_ = false; | ||
64 | 51 | ||
65 | // Set sound gain | 52 | // Set sound gain |
66 | Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) ); | 53 | Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) ); |
67 | 54 | ||
68 | // Unload | ||
69 | clear_track_vars( this ); | ||
70 | |||
71 | // Init rom | 55 | // Init rom |
72 | Rom_init( &this->rom, 0x1000 ); | 56 | Rom_init( &this->rom, bank_size ); |
73 | 57 | ||
74 | // Init & clear nsfe info | 58 | // Init & clear nsfe info |
75 | Info_init( &this->info ); | 59 | Info_init( &this->info ); |
@@ -78,16 +62,36 @@ void Nsf_init( struct Nsf_Emu* this ) | |||
78 | Cpu_init( &this->cpu ); | 62 | Cpu_init( &this->cpu ); |
79 | Apu_init( &this->apu ); | 63 | Apu_init( &this->apu ); |
80 | Apu_dmc_reader( &this->apu, pcm_read, this ); | 64 | Apu_dmc_reader( &this->apu, pcm_read, this ); |
65 | |||
66 | // Unload | ||
67 | this->voice_count = 0; | ||
68 | memset( this->voice_types, 0, sizeof this->voice_types ); | ||
69 | clear_track_vars( this ); | ||
81 | } | 70 | } |
82 | 71 | ||
83 | // Setup | 72 | // Setup |
84 | 73 | ||
74 | static void append_voices( struct Nsf_Emu* this, int const types [], int count ) | ||
75 | { | ||
76 | assert( this->voice_count + count < max_voices ); | ||
77 | int i; | ||
78 | for ( i = 0; i < count; i++ ) { | ||
79 | this->voice_types [this->voice_count + i] = types [i]; | ||
80 | } | ||
81 | this->voice_count += count; | ||
82 | } | ||
83 | |||
85 | static blargg_err_t init_sound( struct Nsf_Emu* this ) | 84 | static blargg_err_t init_sound( struct Nsf_Emu* this ) |
86 | { | 85 | { |
87 | /* if ( header_.chip_flags & ~(fds_flag | namco_flag | vrc6_flag | fme7_flag) ) | 86 | /* if ( header_.chip_flags & ~(fds_flag | namco_flag | vrc6_flag | fme7_flag) ) |
88 | warning( "Uses unsupported audio expansion hardware" ); **/ | 87 | warning( "Uses unsupported audio expansion hardware" ); **/ |
89 | 88 | ||
90 | this->voice_count = apu_osc_count; | 89 | { |
90 | static int const types [apu_osc_count] = { | ||
91 | wave_type+1, wave_type+2, mixed_type+1, noise_type+0, mixed_type+1 | ||
92 | }; | ||
93 | append_voices( this, types, apu_osc_count ); | ||
94 | } | ||
91 | 95 | ||
92 | int adjusted_gain = (this->gain * 4) / 3; | 96 | int adjusted_gain = (this->gain * 4) / 3; |
93 | 97 | ||
@@ -103,7 +107,10 @@ static blargg_err_t init_sound( struct Nsf_Emu* this ) | |||
103 | Vrc6_init( &this->vrc6 ); | 107 | Vrc6_init( &this->vrc6 ); |
104 | adjusted_gain = (adjusted_gain*3) / 4; | 108 | adjusted_gain = (adjusted_gain*3) / 4; |
105 | 109 | ||
106 | this->voice_count += vrc6_osc_count; | 110 | static int const types [vrc6_osc_count] = { |
111 | wave_type+3, wave_type+4, wave_type+5, | ||
112 | }; | ||
113 | append_voices( this, types, vrc6_osc_count ); | ||
107 | } | 114 | } |
108 | 115 | ||
109 | if ( fme7_enabled( this ) ) | 116 | if ( fme7_enabled( this ) ) |
@@ -111,7 +118,10 @@ static blargg_err_t init_sound( struct Nsf_Emu* this ) | |||
111 | Fme7_init( &this->fme7 ); | 118 | Fme7_init( &this->fme7 ); |
112 | adjusted_gain = (adjusted_gain*3) / 4; | 119 | adjusted_gain = (adjusted_gain*3) / 4; |
113 | 120 | ||
114 | this->voice_count += fme7_osc_count; | 121 | static int const types [fme7_osc_count] = { |
122 | wave_type+3, wave_type+4, wave_type+5, | ||
123 | }; | ||
124 | append_voices( this, types, fme7_osc_count ); | ||
115 | } | 125 | } |
116 | 126 | ||
117 | if ( mmc5_enabled( this ) ) | 127 | if ( mmc5_enabled( this ) ) |
@@ -119,7 +129,11 @@ static blargg_err_t init_sound( struct Nsf_Emu* this ) | |||
119 | Mmc5_init( &this->mmc5 ); | 129 | Mmc5_init( &this->mmc5 ); |
120 | adjusted_gain = (adjusted_gain*3) / 4; | 130 | adjusted_gain = (adjusted_gain*3) / 4; |
121 | 131 | ||
122 | this->voice_count += mmc5_osc_count; | 132 | |
133 | static int const types [mmc5_osc_count] = { | ||
134 | wave_type+3, wave_type+4, mixed_type+2 | ||
135 | }; | ||
136 | append_voices( this, types, mmc5_osc_count ); | ||
123 | } | 137 | } |
124 | 138 | ||
125 | if ( fds_enabled( this ) ) | 139 | if ( fds_enabled( this ) ) |
@@ -127,7 +141,10 @@ static blargg_err_t init_sound( struct Nsf_Emu* this ) | |||
127 | Fds_init( &this->fds ); | 141 | Fds_init( &this->fds ); |
128 | adjusted_gain = (adjusted_gain*3) / 4; | 142 | adjusted_gain = (adjusted_gain*3) / 4; |
129 | 143 | ||
130 | this->voice_count += fds_osc_count ; | 144 | static int const types [fds_osc_count] = { |
145 | wave_type+0 | ||
146 | }; | ||
147 | append_voices( this, types, fds_osc_count ); | ||
131 | } | 148 | } |
132 | 149 | ||
133 | if ( namco_enabled( this ) ) | 150 | if ( namco_enabled( this ) ) |
@@ -135,22 +152,31 @@ static blargg_err_t init_sound( struct Nsf_Emu* this ) | |||
135 | Namco_init( &this->namco ); | 152 | Namco_init( &this->namco ); |
136 | adjusted_gain = (adjusted_gain*3) / 4; | 153 | adjusted_gain = (adjusted_gain*3) / 4; |
137 | 154 | ||
138 | this->voice_count += namco_osc_count; | 155 | static int const types [namco_osc_count] = { |
156 | wave_type+3, wave_type+4, wave_type+5, wave_type+ 6, | ||
157 | wave_type+7, wave_type+8, wave_type+9, wave_type+10, | ||
158 | }; | ||
159 | append_voices( this, types, namco_osc_count ); | ||
139 | } | 160 | } |
140 | 161 | ||
141 | if ( vrc7_enabled( this ) ) | ||
142 | { | ||
143 | #ifndef NSF_EMU_NO_VRC7 | 162 | #ifndef NSF_EMU_NO_VRC7 |
163 | if ( vrc7_enabled( this ) ) | ||
164 | { | ||
165 | |||
144 | Vrc7_init( &this->vrc7 ); | 166 | Vrc7_init( &this->vrc7 ); |
145 | Vrc7_set_rate( &this->vrc7, this->sample_rate ); | 167 | Vrc7_set_rate( &this->vrc7, this->sample_rate ); |
146 | #endif | ||
147 | 168 | ||
148 | adjusted_gain = (adjusted_gain*3) / 4; | 169 | adjusted_gain = (adjusted_gain*3) / 4; |
170 | |||
171 | static int const types [vrc7_osc_count] = { | ||
172 | wave_type+3, wave_type+4, wave_type+5, wave_type+6, | ||
173 | wave_type+7, wave_type+8 | ||
174 | }; | ||
175 | append_voices( this, types, vrc7_osc_count ); | ||
176 | } | ||
149 | 177 | ||
150 | this->voice_count += vrc7_osc_count; | 178 | if ( vrc7_enabled( this ) ) Vrc7_volume( &this->vrc7, adjusted_gain ); |
151 | } | 179 | #endif |
152 | |||
153 | if ( vrc7_enabled( this ) ) Vrc7_volume( &this->vrc7, adjusted_gain ); | ||
154 | if ( namco_enabled( this ) ) Namco_volume( &this->namco, adjusted_gain ); | 180 | if ( namco_enabled( this ) ) Namco_volume( &this->namco, adjusted_gain ); |
155 | if ( vrc6_enabled( this ) ) Vrc6_volume( &this->vrc6, adjusted_gain ); | 181 | if ( vrc6_enabled( this ) ) Vrc6_volume( &this->vrc6, adjusted_gain ); |
156 | if ( fme7_enabled( this ) ) Fme7_volume( &this->fme7, adjusted_gain ); | 182 | if ( fme7_enabled( this ) ) Fme7_volume( &this->fme7, adjusted_gain ); |
@@ -179,9 +205,9 @@ static bool pal_only( struct header_t* this ) | |||
179 | return (this->speed_flags & 3) == 1; | 205 | return (this->speed_flags & 3) == 1; |
180 | } | 206 | } |
181 | 207 | ||
182 | static long clock_rate( struct header_t* this ) | 208 | static int clock_rate( struct header_t* this ) |
183 | { | 209 | { |
184 | return pal_only( this ) ? (long)1662607.125 : (long)1789772.727272727; | 210 | return pal_only( this ) ? (int)1662607.125 : (int)1789772.727272727; |
185 | } | 211 | } |
186 | 212 | ||
187 | static int play_period( struct header_t* this ) | 213 | static int play_period( struct header_t* this ) |
@@ -227,7 +253,7 @@ static blargg_err_t check_nsf_header( struct header_t* h ) | |||
227 | return 0; | 253 | return 0; |
228 | } | 254 | } |
229 | 255 | ||
230 | blargg_err_t Nsf_load( struct Nsf_Emu* this, void* data, long size ) | 256 | blargg_err_t Nsf_load_mem( struct Nsf_Emu* this, void* data, long size ) |
231 | { | 257 | { |
232 | // Unload | 258 | // Unload |
233 | Info_unload( &this->info ); // TODO: extremely hacky! | 259 | Info_unload( &this->info ); // TODO: extremely hacky! |
@@ -258,11 +284,10 @@ blargg_err_t Nsf_post_load( struct Nsf_Emu* this ) | |||
258 | warning( "Unknown file version" ); */ | 284 | warning( "Unknown file version" ); */ |
259 | 285 | ||
260 | // set up data | 286 | // set up data |
261 | addr_t load_addr = get_le16( this->header.load_addr ); | 287 | addr_t load_addr = get_addr( this->header.load_addr ); |
262 | |||
263 | /* if ( load_addr < (fds_enabled() ? sram_addr : rom_addr) ) | 288 | /* if ( load_addr < (fds_enabled() ? sram_addr : rom_addr) ) |
264 | warning( "Load address is too low" ); */ | 289 | warning( "Load address is too low" ); */ |
265 | 290 | ||
266 | Rom_set_addr( &this->rom, load_addr % this->rom.bank_size ); | 291 | Rom_set_addr( &this->rom, load_addr % this->rom.bank_size ); |
267 | 292 | ||
268 | /* if ( header_.vers != 1 ) | 293 | /* if ( header_.vers != 1 ) |
@@ -277,17 +302,16 @@ blargg_err_t Nsf_post_load( struct Nsf_Emu* this ) | |||
277 | 302 | ||
278 | // Post load | 303 | // Post load |
279 | Sound_set_tempo( this, this->tempo ); | 304 | Sound_set_tempo( this, this->tempo ); |
280 | |||
281 | // Remute voices | ||
282 | Sound_mute_voices( this, this->mute_mask_ ); | 305 | Sound_mute_voices( this, this->mute_mask_ ); |
283 | 306 | ||
284 | // Set track_count | 307 | // Set track_count |
285 | this->track_count = this->header.track_count; | 308 | this->track_count = this->header.track_count; |
286 | 309 | ||
287 | // Change clock rate & setup buffer | 310 | // Change clock rate & setup buffer |
288 | this->clock_rate__ = (long) clock_rate( &this->header ); | 311 | this->clock_rate__ = clock_rate( &this->header ); |
289 | Buffer_clock_rate( &this->stereo_buf, this->clock_rate__ ); | 312 | Buffer_clock_rate( &this->stereo_buf, this->clock_rate__ ); |
290 | this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); | 313 | RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) ); |
314 | this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); | ||
291 | return 0; | 315 | return 0; |
292 | } | 316 | } |
293 | 317 | ||
@@ -416,11 +440,13 @@ static void set_voice( struct Nsf_Emu* this, int i, struct Blip_Buffer* buf, str | |||
416 | return; | 440 | return; |
417 | } | 441 | } |
418 | 442 | ||
419 | if ( vrc7_enabled( this ) && (i -= vrc7_osc_count) < 0 ) | 443 | #ifndef NSF_EMU_NO_VRC7 |
420 | { | 444 | if ( vrc7_enabled( this ) && (i -= vrc7_osc_count) < 0 ) |
421 | Vrc7_set_output( &this->vrc7, i + vrc7_osc_count, buf ); | 445 | { |
422 | return; | 446 | Vrc7_set_output( &this->vrc7, i + vrc7_osc_count, buf ); |
423 | } | 447 | return; |
448 | } | ||
449 | #endif | ||
424 | } | 450 | } |
425 | #endif | 451 | #endif |
426 | } | 452 | } |
@@ -429,7 +455,7 @@ static void set_voice( struct Nsf_Emu* this, int i, struct Blip_Buffer* buf, str | |||
429 | 455 | ||
430 | // Music Emu | 456 | // Music Emu |
431 | 457 | ||
432 | blargg_err_t Nsf_set_sample_rate( struct Nsf_Emu* this, long rate ) | 458 | blargg_err_t Nsf_set_sample_rate( struct Nsf_Emu* this, int rate ) |
433 | { | 459 | { |
434 | require( !this->sample_rate ); // sample rate can't be changed once set | 460 | require( !this->sample_rate ); // sample rate can't be changed once set |
435 | Buffer_init( &this->stereo_buf ); | 461 | Buffer_init( &this->stereo_buf ); |
@@ -439,6 +465,8 @@ blargg_err_t Nsf_set_sample_rate( struct Nsf_Emu* this, long rate ) | |||
439 | Buffer_bass_freq( &this->stereo_buf, 80 ); | 465 | Buffer_bass_freq( &this->stereo_buf, 80 ); |
440 | 466 | ||
441 | this->sample_rate = rate; | 467 | this->sample_rate = rate; |
468 | RETURN_ERR( track_init( &this->track_filter, this ) ); | ||
469 | this->tfilter.max_silence = 6 * stereo * this->sample_rate; | ||
442 | return 0; | 470 | return 0; |
443 | } | 471 | } |
444 | 472 | ||
@@ -466,7 +494,7 @@ void Sound_mute_voices( struct Nsf_Emu* this, int mask ) | |||
466 | } | 494 | } |
467 | else | 495 | else |
468 | { | 496 | { |
469 | struct channel_t ch = Buffer_channel( &this->stereo_buf ); | 497 | struct channel_t ch = Buffer_channel( &this->stereo_buf, i ); |
470 | assert( (ch.center && ch.left && ch.right) || | 498 | assert( (ch.center && ch.left && ch.right) || |
471 | (!ch.center && !ch.left && !ch.right) ); // all or nothing | 499 | (!ch.center && !ch.left && !ch.right) ); // all or nothing |
472 | set_voice( this, i, ch.center, ch.left, ch.right ); | 500 | set_voice( this, i, ch.center, ch.left, ch.right ); |
@@ -533,32 +561,13 @@ int cpu_read( struct Nsf_Emu* this, addr_t addr ) | |||
533 | return addr >> 8; | 561 | return addr >> 8; |
534 | } | 562 | } |
535 | 563 | ||
536 | #if 0 /* function currently unused */ | ||
537 | static int unmapped_read( struct Nsf_Emu* this, addr_t addr ) | ||
538 | { | ||
539 | (void) this; | ||
540 | |||
541 | switch ( addr ) | ||
542 | { | ||
543 | case 0x2002: | ||
544 | case 0x4016: | ||
545 | case 0x4017: | ||
546 | return addr >> 8; | ||
547 | } | ||
548 | |||
549 | // Unmapped read | ||
550 | return addr >> 8; | ||
551 | } | ||
552 | #endif | ||
553 | |||
554 | void cpu_write( struct Nsf_Emu* this, addr_t addr, int data ) | 564 | void cpu_write( struct Nsf_Emu* this, addr_t addr, int data ) |
555 | { | 565 | { |
556 | #ifndef NSF_EMU_APU_ONLY | 566 | #ifndef NSF_EMU_APU_ONLY |
557 | { | 567 | { |
558 | nes_time_t time = Cpu_time( &this->cpu ); | ||
559 | if ( fds_enabled( this) && (unsigned) (addr - fds_io_addr) < fds_io_size ) | 568 | if ( fds_enabled( this) && (unsigned) (addr - fds_io_addr) < fds_io_size ) |
560 | { | 569 | { |
561 | Fds_write( &this->fds, time, addr, data ); | 570 | Fds_write( &this->fds, Cpu_time( &this->cpu ), addr, data ); |
562 | return; | 571 | return; |
563 | } | 572 | } |
564 | 573 | ||
@@ -572,7 +581,7 @@ void cpu_write( struct Nsf_Emu* this, addr_t addr, int data ) | |||
572 | 581 | ||
573 | if ( addr == namco_data_reg_addr ) | 582 | if ( addr == namco_data_reg_addr ) |
574 | { | 583 | { |
575 | Namco_write_data( &this->namco, time, data ); | 584 | Namco_write_data( &this->namco, Cpu_time( &this->cpu ), data ); |
576 | return; | 585 | return; |
577 | } | 586 | } |
578 | } | 587 | } |
@@ -583,7 +592,7 @@ void cpu_write( struct Nsf_Emu* this, addr_t addr, int data ) | |||
583 | int osc = (unsigned) (addr - vrc6_base_addr) / vrc6_addr_step; | 592 | int osc = (unsigned) (addr - vrc6_base_addr) / vrc6_addr_step; |
584 | if ( (unsigned) osc < vrc6_osc_count && (unsigned) reg < vrc6_reg_count ) | 593 | if ( (unsigned) osc < vrc6_osc_count && (unsigned) reg < vrc6_reg_count ) |
585 | { | 594 | { |
586 | Vrc6_write_osc( &this->vrc6, time, osc, reg, data ); | 595 | Vrc6_write_osc( &this->vrc6, Cpu_time( &this->cpu ), osc, reg, data ); |
587 | return; | 596 | return; |
588 | } | 597 | } |
589 | } | 598 | } |
@@ -597,7 +606,7 @@ void cpu_write( struct Nsf_Emu* this, addr_t addr, int data ) | |||
597 | return; | 606 | return; |
598 | 607 | ||
599 | case fme7_data_addr: | 608 | case fme7_data_addr: |
600 | Fme7_write_data( &this->fme7, time, data ); | 609 | Fme7_write_data( &this->fme7, Cpu_time( &this->cpu ), data ); |
601 | return; | 610 | return; |
602 | } | 611 | } |
603 | } | 612 | } |
@@ -606,7 +615,7 @@ void cpu_write( struct Nsf_Emu* this, addr_t addr, int data ) | |||
606 | { | 615 | { |
607 | if ( (unsigned) (addr - mmc5_regs_addr) < mmc5_regs_size ) | 616 | if ( (unsigned) (addr - mmc5_regs_addr) < mmc5_regs_size ) |
608 | { | 617 | { |
609 | Mmc5_write_register( &this->mmc5, time, addr, data ); | 618 | Mmc5_write_register( &this->mmc5, Cpu_time( &this->cpu ), addr, data ); |
610 | return; | 619 | return; |
611 | } | 620 | } |
612 | 621 | ||
@@ -625,49 +634,28 @@ void cpu_write( struct Nsf_Emu* this, addr_t addr, int data ) | |||
625 | } | 634 | } |
626 | } | 635 | } |
627 | 636 | ||
628 | if ( vrc7_enabled( this) ) | 637 | #ifndef NSF_EMU_NO_VRC7 |
629 | { | 638 | if ( vrc7_enabled( this) ) |
630 | if ( addr == 0x9010 ) | ||
631 | { | 639 | { |
632 | Vrc7_write_reg( &this->vrc7, data ); | 640 | if ( addr == 0x9010 ) |
633 | return; | 641 | { |
634 | } | 642 | Vrc7_write_reg( &this->vrc7, data ); |
643 | return; | ||
644 | } | ||
635 | 645 | ||
636 | if ( (unsigned) (addr - 0x9028) <= 0x08 ) | 646 | if ( (unsigned) (addr - 0x9028) <= 0x08 ) |
637 | { | 647 | { |
638 | Vrc7_write_data( &this->vrc7, time, data ); | 648 | Vrc7_write_data( &this->vrc7, Cpu_time( &this->cpu ), data ); |
639 | return; | 649 | return; |
650 | } | ||
640 | } | 651 | } |
641 | } | 652 | #endif |
642 | } | 653 | } |
643 | #endif | 654 | #endif |
644 | 655 | ||
645 | // Unmapped_write | 656 | // Unmapped_write |
646 | } | 657 | } |
647 | 658 | ||
648 | #if 0 /* function currently unused */ | ||
649 | static void unmapped_write( struct Nsf_Emu* this, addr_t addr, int data ) | ||
650 | { | ||
651 | (void) data; | ||
652 | |||
653 | switch ( addr ) | ||
654 | { | ||
655 | case 0x8000: // some write to $8000 and $8001 repeatedly | ||
656 | case 0x8001: | ||
657 | case 0x4800: // probably namco sound mistakenly turned on in MCK | ||
658 | case 0xF800: | ||
659 | case 0xFFF8: // memory mapper? | ||
660 | return; | ||
661 | } | ||
662 | |||
663 | if ( mmc5_enabled( this ) && addr == 0x5115 ) return; | ||
664 | |||
665 | // FDS memory | ||
666 | if ( fds_enabled( this ) && (unsigned) (addr - 0x8000) < 0x6000 ) return; | ||
667 | } | ||
668 | #endif | ||
669 | |||
670 | void fill_buf( struct Nsf_Emu* this ); | ||
671 | blargg_err_t Nsf_start_track( struct Nsf_Emu* this, int track ) | 659 | blargg_err_t Nsf_start_track( struct Nsf_Emu* this, int track ) |
672 | { | 660 | { |
673 | clear_track_vars( this ); | 661 | clear_track_vars( this ); |
@@ -695,7 +683,9 @@ blargg_err_t Nsf_start_track( struct Nsf_Emu* this, int track ) | |||
695 | if ( vrc6_enabled( this ) ) Vrc6_reset( &this->vrc6 ); | 683 | if ( vrc6_enabled( this ) ) Vrc6_reset( &this->vrc6 ); |
696 | if ( fme7_enabled( this ) ) Fme7_reset( &this->fme7 ); | 684 | if ( fme7_enabled( this ) ) Fme7_reset( &this->fme7 ); |
697 | if ( mmc5_enabled( this ) ) Apu_reset( &this->mmc5.apu, false, 0 ); | 685 | if ( mmc5_enabled( this ) ) Apu_reset( &this->mmc5.apu, false, 0 ); |
698 | if ( vrc7_enabled( this ) ) Vrc7_reset( &this->vrc7 ); | 686 | #ifndef NSF_EMU_NO_VRC7 |
687 | if ( vrc7_enabled( this ) ) Vrc7_reset( &this->vrc7 ); | ||
688 | #endif | ||
699 | #endif | 689 | #endif |
700 | 690 | ||
701 | int speed_flags = 0; | 691 | int speed_flags = 0; |
@@ -728,27 +718,15 @@ blargg_err_t Nsf_start_track( struct Nsf_Emu* this, int track ) | |||
728 | /* if ( this->cpu.r.pc < get_addr( header.load_addr ) ) | 718 | /* if ( this->cpu.r.pc < get_addr( header.load_addr ) ) |
729 | warning( "Init address < load address" ); */ | 719 | warning( "Init address < load address" ); */ |
730 | 720 | ||
731 | this->emu_track_ended_ = false; | 721 | // convert filter times to samples |
732 | this->track_ended = false; | 722 | struct setup_t s = this->tfilter; |
723 | s.max_initial *= this->sample_rate * stereo; | ||
724 | #ifdef GME_DISABLE_SILENCE_LOOKAHEAD | ||
725 | s.lookahead = 1; | ||
726 | #endif | ||
727 | track_setup( &this->track_filter, &s ); | ||
733 | 728 | ||
734 | if ( !this->ignore_silence ) | 729 | return track_start( &this->track_filter ); |
735 | { | ||
736 | // play until non-silence or end of track | ||
737 | long end; | ||
738 | for ( end = this->max_initial_silence * stereo * this->sample_rate; this->emu_time < end; ) | ||
739 | { | ||
740 | fill_buf( this ); | ||
741 | if ( this->buf_remain | (int) this->emu_track_ended_ ) | ||
742 | break; | ||
743 | } | ||
744 | |||
745 | this->emu_time = this->buf_remain; | ||
746 | this->out_time = 0; | ||
747 | this->silence_time = 0; | ||
748 | this->silence_count = 0; | ||
749 | } | ||
750 | /* return track_ended() ? warning() : 0; */ | ||
751 | return 0; | ||
752 | } | 730 | } |
753 | 731 | ||
754 | void run_once( struct Nsf_Emu* this, nes_time_t end ) | 732 | void run_once( struct Nsf_Emu* this, nes_time_t end ) |
@@ -831,265 +809,99 @@ static void end_frame( struct Nsf_Emu* this, nes_time_t end ) | |||
831 | if ( mmc5_enabled( this ) ) Apu_end_frame( &this->mmc5.apu, end ); | 809 | if ( mmc5_enabled( this ) ) Apu_end_frame( &this->mmc5.apu, end ); |
832 | if ( namco_enabled( this ) ) Namco_end_frame( &this->namco, end ); | 810 | if ( namco_enabled( this ) ) Namco_end_frame( &this->namco, end ); |
833 | if ( vrc6_enabled( this ) ) Vrc6_end_frame( &this->vrc6, end ); | 811 | if ( vrc6_enabled( this ) ) Vrc6_end_frame( &this->vrc6, end ); |
812 | #ifndef NSF_EMU_NO_VRC7 | ||
834 | if ( vrc7_enabled( this ) ) Vrc7_end_frame( &this->vrc7, end ); | 813 | if ( vrc7_enabled( this ) ) Vrc7_end_frame( &this->vrc7, end ); |
814 | #endif | ||
835 | #endif | 815 | #endif |
836 | } | 816 | } |
837 | 817 | ||
838 | // Tell/Seek | 818 | // Tell/Seek |
839 | 819 | ||
840 | static blargg_long msec_to_samples( long sample_rate, blargg_long msec ) | 820 | static int msec_to_samples( int msec, int sample_rate ) |
841 | { | 821 | { |
842 | blargg_long sec = msec / 1000; | 822 | int sec = msec / 1000; |
843 | msec -= sec * 1000; | 823 | msec -= sec * 1000; |
844 | return (sec * sample_rate + msec * sample_rate / 1000) * stereo; | 824 | return (sec * sample_rate + msec * sample_rate / 1000) * stereo; |
845 | } | 825 | } |
846 | 826 | ||
847 | long Track_tell( struct Nsf_Emu* this ) | 827 | int Track_tell( struct Nsf_Emu* this ) |
848 | { | 828 | { |
849 | blargg_long rate = this->sample_rate * stereo; | 829 | int rate = this->sample_rate * stereo; |
850 | blargg_long sec = this->out_time / rate; | 830 | int sec = track_sample_count( &this->track_filter ) / rate; |
851 | return sec * 1000 + (this->out_time - sec * rate) * 1000 / rate; | 831 | return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate; |
852 | } | 832 | } |
853 | 833 | ||
854 | blargg_err_t Track_seek( struct Nsf_Emu* this, long msec ) | 834 | blargg_err_t Track_seek( struct Nsf_Emu* this, int msec ) |
855 | { | 835 | { |
856 | blargg_long time = msec_to_samples( this->sample_rate, msec ); | 836 | int time = msec_to_samples( msec, this->sample_rate ); |
857 | if ( time < this->out_time ) | 837 | if ( time < track_sample_count( &this->track_filter ) ) |
858 | RETURN_ERR( Nsf_start_track( this, this->current_track ) ); | 838 | RETURN_ERR( Nsf_start_track( this, this->current_track ) ); |
859 | return Track_skip( this, time - this->out_time ); | 839 | return Track_skip( this, time - track_sample_count( &this->track_filter ) ); |
860 | } | 840 | } |
861 | 841 | ||
862 | blargg_err_t skip_( struct Nsf_Emu* this, long count ); | 842 | blargg_err_t Track_skip( struct Nsf_Emu* this, int count ) |
863 | blargg_err_t Track_skip( struct Nsf_Emu* this, long count ) | ||
864 | { | 843 | { |
865 | require( this->current_track >= 0 ); // start_track() must have been called already | 844 | require( this->current_track >= 0 ); // start_track() must have been called already |
866 | this->out_time += count; | 845 | return track_skip( &this->track_filter, count ); |
867 | |||
868 | // remove from silence and buf first | ||
869 | { | ||
870 | long n = min( count, this->silence_count ); | ||
871 | this->silence_count -= n; | ||
872 | count -= n; | ||
873 | |||
874 | n = min( count, this->buf_remain ); | ||
875 | this->buf_remain -= n; | ||
876 | count -= n; | ||
877 | } | ||
878 | |||
879 | if ( count && !this->emu_track_ended_ ) | ||
880 | { | ||
881 | this->emu_time += count; | ||
882 | // End track if error | ||
883 | if ( skip_( this, count ) ) | ||
884 | this->emu_track_ended_ = true; | ||
885 | } | ||
886 | |||
887 | if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended | ||
888 | this->track_ended |= this->emu_track_ended_; | ||
889 | |||
890 | return 0; | ||
891 | } | 846 | } |
892 | 847 | ||
893 | blargg_err_t play_( struct Nsf_Emu* this, long count, sample_t* out ); | 848 | blargg_err_t skip_( void *emu, int count ) |
894 | blargg_err_t skip_( struct Nsf_Emu* this, long count ) | ||
895 | { | 849 | { |
850 | struct Nsf_Emu* this = (struct Nsf_Emu*) emu; | ||
851 | |||
896 | // for long skip, mute sound | 852 | // for long skip, mute sound |
897 | const long threshold = 30000; | 853 | const int threshold = 32768; |
898 | if ( count > threshold ) | 854 | if ( count > threshold ) |
899 | { | 855 | { |
900 | int saved_mute = this->mute_mask_; | 856 | int saved_mute = this->mute_mask_; |
901 | Sound_mute_voices( this, ~0 ); | 857 | Sound_mute_voices( this, ~0 ); |
902 | |||
903 | while ( count > threshold / 2 && !this->emu_track_ended_ ) | ||
904 | { | ||
905 | RETURN_ERR( play_( this, buf_size, this->buf ) ); | ||
906 | count -= buf_size; | ||
907 | } | ||
908 | |||
909 | Sound_mute_voices( this, saved_mute ); | ||
910 | } | ||
911 | |||
912 | while ( count && !this->emu_track_ended_ ) | ||
913 | { | ||
914 | long n = buf_size; | ||
915 | if ( n > count ) | ||
916 | n = count; | ||
917 | count -= n; | ||
918 | RETURN_ERR( play_( this, n, this->buf ) ); | ||
919 | } | ||
920 | return 0; | ||
921 | } | ||
922 | |||
923 | // Fading | ||
924 | 858 | ||
925 | void Track_set_fade( struct Nsf_Emu* this, long start_msec, long length_msec ) | 859 | int n = count - threshold/2; |
926 | { | 860 | n &= ~(2048-1); // round to multiple of 2048 |
927 | this->fade_step = this->sample_rate * length_msec / (fade_block_size * fade_shift * 1000 / stereo); | 861 | count -= n; |
928 | this->fade_start = msec_to_samples( this->sample_rate, start_msec ); | 862 | RETURN_ERR( skippy_( &this->track_filter, n ) ); |
929 | } | ||
930 | |||
931 | // unit / pow( 2.0, (double) x / step ) | ||
932 | static int int_log( blargg_long x, int step, int unit ) | ||
933 | { | ||
934 | int shift = x / step; | ||
935 | int fraction = (x - shift * step) * unit / step; | ||
936 | return ((unit - fraction) + (fraction >> 1)) >> shift; | ||
937 | } | ||
938 | 863 | ||
939 | static void handle_fade( struct Nsf_Emu* this, long out_count, sample_t* out ) | 864 | Sound_mute_voices( this, saved_mute ); |
940 | { | ||
941 | int i; | ||
942 | for ( i = 0; i < out_count; i += fade_block_size ) | ||
943 | { | ||
944 | int const shift = 14; | ||
945 | int const unit = 1 << shift; | ||
946 | int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size, | ||
947 | this->fade_step, unit ); | ||
948 | if ( gain < (unit >> fade_shift) ) | ||
949 | this->track_ended = this->emu_track_ended_ = true; | ||
950 | |||
951 | sample_t* io = &out [i]; | ||
952 | int count; | ||
953 | for ( count = min( fade_block_size, out_count - i ); count; --count ) | ||
954 | { | ||
955 | *io = (sample_t) ((*io * gain) >> shift); | ||
956 | ++io; | ||
957 | } | ||
958 | } | 865 | } |
959 | } | ||
960 | |||
961 | // Silence detection | ||
962 | 866 | ||
963 | void emu_play( struct Nsf_Emu* this, long count, sample_t* out ); | 867 | return skippy_( &this->track_filter, count ); |
964 | void emu_play( struct Nsf_Emu* this, long count, sample_t* out ) | ||
965 | { | ||
966 | check( current_track_ >= 0 ); | ||
967 | this->emu_time += count; | ||
968 | if ( this->current_track >= 0 && !this->emu_track_ended_ ) { | ||
969 | |||
970 | // End track if error | ||
971 | if ( play_( this, count, out ) ) | ||
972 | this->emu_track_ended_ = true; | ||
973 | } | ||
974 | else | ||
975 | memset( out, 0, count * sizeof *out ); | ||
976 | } | 868 | } |
977 | 869 | ||
978 | // number of consecutive silent samples at end | 870 | // Fading |
979 | static long count_silence( sample_t* begin, long size ) | ||
980 | { | ||
981 | sample_t first = *begin; | ||
982 | *begin = silence_threshold; // sentinel | ||
983 | sample_t* p = begin + size; | ||
984 | while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { } | ||
985 | *begin = first; | ||
986 | return size - (p - begin); | ||
987 | } | ||
988 | 871 | ||
989 | // fill internal buffer and check it for silence | 872 | void Track_set_fade( struct Nsf_Emu* this, int start_msec, int length_msec ) |
990 | void fill_buf( struct Nsf_Emu* this ) | ||
991 | { | 873 | { |
992 | assert( !this->buf_remain ); | 874 | track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ), |
993 | if ( !this->emu_track_ended_ ) | 875 | length_msec * this->sample_rate / (1000 / stereo) ); |
994 | { | ||
995 | emu_play( this, buf_size, this->buf ); | ||
996 | long silence = count_silence( this->buf, buf_size ); | ||
997 | if ( silence < buf_size ) | ||
998 | { | ||
999 | this->silence_time = this->emu_time - silence; | ||
1000 | this->buf_remain = buf_size; | ||
1001 | return; | ||
1002 | } | ||
1003 | } | ||
1004 | this->silence_count += buf_size; | ||
1005 | } | 876 | } |
1006 | 877 | ||
1007 | blargg_err_t Nsf_play( struct Nsf_Emu* this, long out_count, sample_t* out ) | 878 | blargg_err_t Nsf_play( struct Nsf_Emu* this, int out_count, sample_t* out ) |
1008 | { | 879 | { |
1009 | if ( this->track_ended ) | 880 | require( this->current_track >= 0 ); |
1010 | { | 881 | require( out_count % stereo == 0 ); |
1011 | memset( out, 0, out_count * sizeof *out ); | 882 | return track_play( &this->track_filter, out_count, out ); |
1012 | } | ||
1013 | else | ||
1014 | { | ||
1015 | require( this->current_track >= 0 ); | ||
1016 | require( out_count % stereo == 0 ); | ||
1017 | |||
1018 | assert( this->emu_time >= this->out_time ); | ||
1019 | |||
1020 | long pos = 0; | ||
1021 | if ( this->silence_count ) | ||
1022 | { | ||
1023 | // during a run of silence, run emulator at >=2x speed so it gets ahead | ||
1024 | long ahead_time = this->silence_lookahead * (this->out_time + out_count - this->silence_time) + this->silence_time; | ||
1025 | while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) ) | ||
1026 | fill_buf( this ); | ||
1027 | |||
1028 | // fill with silence | ||
1029 | pos = min( this->silence_count, out_count ); | ||
1030 | memset( out, 0, pos * sizeof *out ); | ||
1031 | this->silence_count -= pos; | ||
1032 | |||
1033 | if ( this->emu_time - this->silence_time > silence_max * stereo * this->sample_rate ) | ||
1034 | { | ||
1035 | this->track_ended = this->emu_track_ended_ = true; | ||
1036 | this->silence_count = 0; | ||
1037 | this->buf_remain = 0; | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1041 | if ( this->buf_remain ) | ||
1042 | { | ||
1043 | // empty silence buf | ||
1044 | long n = min( this->buf_remain, out_count - pos ); | ||
1045 | memcpy( &out [pos], this->buf + (buf_size - this->buf_remain), n * sizeof *out ); | ||
1046 | this->buf_remain -= n; | ||
1047 | pos += n; | ||
1048 | } | ||
1049 | |||
1050 | // generate remaining samples normally | ||
1051 | long remain = out_count - pos; | ||
1052 | if ( remain ) | ||
1053 | { | ||
1054 | emu_play( this, remain, out + pos ); | ||
1055 | this->track_ended |= this->emu_track_ended_; | ||
1056 | |||
1057 | if ( !this->ignore_silence || this->out_time > this->fade_start ) | ||
1058 | { | ||
1059 | // check end for a new run of silence | ||
1060 | long silence = count_silence( out + pos, remain ); | ||
1061 | if ( silence < remain ) | ||
1062 | this->silence_time = this->emu_time - silence; | ||
1063 | |||
1064 | if ( this->emu_time - this->silence_time >= buf_size ) | ||
1065 | fill_buf( this ); // cause silence detection on next play() | ||
1066 | } | ||
1067 | } | ||
1068 | |||
1069 | if ( this->out_time > this->fade_start ) | ||
1070 | handle_fade( this, out_count, out ); | ||
1071 | } | ||
1072 | this->out_time += out_count; | ||
1073 | return 0; | ||
1074 | } | 883 | } |
1075 | 884 | ||
1076 | blargg_err_t play_( struct Nsf_Emu* this, long count, sample_t* out ) | 885 | blargg_err_t play_( void* emu, int count, sample_t* out ) |
1077 | { | 886 | { |
1078 | long remain = count; | 887 | struct Nsf_Emu* this = (struct Nsf_Emu*) emu; |
888 | |||
889 | int remain = count; | ||
1079 | while ( remain ) | 890 | while ( remain ) |
1080 | { | 891 | { |
892 | Buffer_disable_immediate_removal( &this->stereo_buf ); | ||
1081 | remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain ); | 893 | remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain ); |
1082 | if ( remain ) | 894 | if ( remain ) |
1083 | { | 895 | { |
1084 | if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) ) | 896 | if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) ) |
1085 | { | 897 | { |
1086 | this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); | 898 | this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); |
1087 | 899 | ||
1088 | // Remute voices | 900 | // Remute voices |
1089 | Sound_mute_voices( this, this->mute_mask_ ); | 901 | Sound_mute_voices( this, this->mute_mask_ ); |
1090 | } | 902 | } |
1091 | int msec = Buffer_length( &this->stereo_buf ); | 903 | int msec = Buffer_length( &this->stereo_buf ); |
1092 | blip_time_t clocks_emulated = (blargg_long) msec * this->clock_rate__ / 1000 - 100; | 904 | blip_time_t clocks_emulated = msec * this->clock_rate__ / 1000 - 100; |
1093 | RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) ); | 905 | RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) ); |
1094 | assert( clocks_emulated ); | 906 | assert( clocks_emulated ); |
1095 | Buffer_end_frame( &this->stereo_buf, clocks_emulated ); | 907 | Buffer_end_frame( &this->stereo_buf, clocks_emulated ); |