Submit initial patch from FS#12176. Adds support for several new game music formats...
[kugel-rb.git] / apps / codecs / libgme / nsf_emu.c
blobc805780cb187fe30074df1a05467b9bad30a4a4f
1 // Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
3 #include "nsf_emu.h"
4 #include "multi_buffer.h"
6 #include "blargg_endian.h"
8 /* Copyright (C) 2003-2006 Shay Green. This module is free software; you
9 can redistribute it and/or modify it under the terms of the GNU Lesser
10 General Public License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version. This
12 module is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15 details. You should have received a copy of the GNU Lesser General Public
16 License along with this module; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
19 #include "blargg_source.h"
21 const char gme_wrong_file_type [] ICONST_ATTR = "Wrong file type for this emulator";
22 long const clock_divisor = 12;
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)
30 // number of frames until play interrupts init
31 int const initial_play_delay = 7; // KikiKaikai needed this to work
32 int const rom_addr = 0x8000;
34 void clear_track_vars( struct Nsf_Emu* this )
36 this->current_track = -1;
37 this->out_time = 0;
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;
48 static int pcm_read( void* emu, addr_t addr )
50 return *Cpu_get_code( &((struct Nsf_Emu*) emu)->cpu, addr );
53 void Nsf_init( struct Nsf_Emu* this )
55 this->sample_rate = 0;
56 this->mute_mask_ = 0;
57 this->tempo = 1.0;
58 this->gain = 1.0;
60 // defaults
61 this->max_initial_silence = 2;
62 this->ignore_silence = false;
63 this->voice_count = 0;
65 // Set sound gain
66 Sound_set_gain( this, 1.2 );
68 // Unload
69 clear_track_vars( this );
71 // Init rom
72 Rom_init( &this->rom, 0x1000 );
74 // Init & clear nsfe info
75 Info_init( &this->info );
76 Info_unload( &this->info ); // TODO: extremely hacky!
78 Cpu_init( &this->cpu );
79 Apu_init( &this->apu );
80 Apu_dmc_reader( &this->apu, pcm_read, this );
83 // Setup
85 blargg_err_t init_sound( struct Nsf_Emu* this )
87 /* if ( header_.chip_flags & ~(fds_flag | namco_flag | vrc6_flag | fme7_flag) )
88 warning( "Uses unsupported audio expansion hardware" ); **/
90 this->voice_count = apu_osc_count;
92 double adjusted_gain = 1.0 / 0.75 * this->gain;
94 #ifdef NSF_EMU_APU_ONLY
96 if ( this->header_.chip_flags )
97 set_warning( "Uses unsupported audio expansion hardware" );
99 #else
101 if ( vrc6_enabled( this ) )
103 Vrc6_init( &this->vrc6 );
104 adjusted_gain *= 0.75;
106 this->voice_count += vrc6_osc_count;
109 if ( fme7_enabled( this ) )
111 Fme7_init( &this->fme7 );
112 adjusted_gain *= 0.75;
114 this->voice_count += fme7_osc_count;
117 if ( mmc5_enabled( this ) )
119 Mmc5_init( &this->mmc5 );
120 adjusted_gain *= 0.75;
122 this->voice_count += mmc5_osc_count;
125 if ( fds_enabled( this ) )
127 Fds_init( &this->fds );
128 adjusted_gain *= 0.75;
130 this->voice_count += fds_osc_count ;
133 if ( namco_enabled( this ) )
135 Namco_init( &this->namco );
136 adjusted_gain *= 0.75;
138 this->voice_count += namco_osc_count;
141 if ( vrc7_enabled( this ) )
143 #ifndef NSF_EMU_NO_VRC7
144 Vrc7_init( &this->vrc7 );
145 Vrc7_set_rate( &this->vrc7, this->sample_rate );
146 #endif
148 adjusted_gain *= 0.75;
150 this->voice_count += vrc7_osc_count;
153 if ( vrc7_enabled( this ) ) Vrc7_volume( &this->vrc7, adjusted_gain );
154 if ( namco_enabled( this ) ) Namco_volume( &this->namco, adjusted_gain );
155 if ( vrc6_enabled( this ) ) Vrc6_volume( &this->vrc6, adjusted_gain );
156 if ( fme7_enabled( this ) ) Fme7_volume( &this->fme7, adjusted_gain );
157 if ( mmc5_enabled( this ) ) Apu_volume( &this->mmc5.apu, adjusted_gain );
158 if ( fds_enabled( this ) ) Fds_volume( &this->fds, adjusted_gain );
160 #endif
162 if ( adjusted_gain > this->gain )
163 adjusted_gain = this->gain;
165 Apu_volume( &this->apu, adjusted_gain );
167 return 0;
170 // Header stuff
171 bool valid_tag( struct header_t* this )
173 return 0 == memcmp( this->tag, "NESM\x1A", 5 );
176 // True if file supports only PAL speed
177 static bool pal_only( struct header_t* this )
179 return (this->speed_flags & 3) == 1;
182 static double clock_rate( struct header_t* this )
184 return pal_only( this ) ? 1662607.125 : 1789772.727272727;
187 int play_period( struct header_t* this )
189 // NTSC
190 int clocks = 29780;
191 int value = 0x411A;
192 byte const* rate_ptr = this->ntsc_speed;
194 // PAL
195 if ( pal_only( this ) )
197 clocks = 33247;
198 value = 0x4E20;
199 rate_ptr = this->pal_speed;
202 // Default rate
203 int rate = get_le16( rate_ptr );
204 if ( rate == 0 )
205 rate = value;
207 // Custom rate
208 if ( rate != value )
209 clocks = (int) (rate * clock_rate( this ) * (1.0/1000000.0));
211 return clocks;
214 // Gets address, given pointer to it in file header. If zero, returns rom_addr.
215 addr_t get_addr( byte const in [] )
217 addr_t addr = get_le16( in );
218 if ( addr == 0 )
219 addr = rom_addr;
220 return addr;
223 static blargg_err_t check_nsf_header( struct header_t* h )
225 if ( !valid_tag( h ) )
226 return gme_wrong_file_type;
227 return 0;
230 blargg_err_t Nsf_load( struct Nsf_Emu* this, void* data, long size )
232 // Unload
233 Info_unload( &this->info ); // TODO: extremely hacky!
234 this->m3u.size = 0;
236 this->voice_count = 0;
237 clear_track_vars( this );
239 assert( offsetof (struct header_t,unused [4]) == header_size );
241 if ( !memcmp( data, "NESM\x1A", 5 ) ) {
242 Nsf_disable_playlist( this, true );
244 RETURN_ERR( Rom_load( &this->rom, data, size, header_size, &this->header, 0 ) );
245 return Nsf_post_load( this );
248 blargg_err_t err = Info_load( &this->info, data, size, this );
249 Nsf_disable_playlist( this, false );
250 return err;
253 blargg_err_t Nsf_post_load( struct Nsf_Emu* this )
255 RETURN_ERR( check_nsf_header( &this->header ) );
257 /* if ( header_.vers != 1 )
258 warning( "Unknown file version" ); */
260 // set up data
261 addr_t load_addr = get_le16( this->header.load_addr );
263 /* if ( load_addr < (fds_enabled() ? sram_addr : rom_addr) )
264 warning( "Load address is too low" ); */
266 Rom_set_addr( &this->rom, load_addr % this->rom.bank_size );
268 /* if ( header_.vers != 1 )
269 warning( "Unknown file version" ); */
271 set_play_period( this, play_period( &this->header ) );
273 // sound and memory
274 blargg_err_t err = init_sound( this );
275 if ( err )
276 return err;
278 // Post load
279 Sound_set_tempo( this, this->tempo );
281 // Remute voices
282 Sound_mute_voices( this, this->mute_mask_ );
284 // Set track_count
285 this->track_count = this->header.track_count;
287 // Change clock rate & setup buffer
288 this->clock_rate__ = (long) (clock_rate( &this->header ) + 0.5);
289 Buffer_clock_rate( &this->stereo_buf, this->clock_rate__ );
290 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
291 return 0;
294 void Nsf_disable_playlist( struct Nsf_Emu* this, bool b )
296 Info_disable_playlist( &this->info, b );
297 this->track_count = this->info.track_count;
300 void Nsf_clear_playlist( struct Nsf_Emu* this )
302 Nsf_disable_playlist( this, true );
305 void write_bank( struct Nsf_Emu* this, int bank, int data )
307 // Find bank in ROM
308 int offset = mask_addr( data * this->rom.bank_size, this->rom.mask );
309 /* if ( offset >= rom.size() )
310 warning( "invalid bank" ); */
311 void const* rom_data = Rom_at_addr( &this->rom, offset );
313 #ifndef NSF_EMU_APU_ONLY
314 if ( bank < bank_count - fds_banks && fds_enabled( this ) )
316 // TODO: FDS bank switching is kind of hacky, might need to
317 // treat ROM as RAM so changes won't get lost when switching.
318 byte* out = sram( this );
319 if ( bank >= fds_banks )
321 out = fdsram( this );
322 bank -= fds_banks;
324 memcpy( &out [bank * this->rom.bank_size], rom_data, this->rom.bank_size );
325 return;
327 #endif
329 if ( bank >= fds_banks )
330 Cpu_map_code( &this->cpu, (bank + 6) * this->rom.bank_size, this->rom.bank_size, rom_data, false );
333 void map_memory( struct Nsf_Emu* this )
335 // Map standard things
336 Cpu_reset( &this->cpu, unmapped_code( this ) );
337 Cpu_map_code( &this->cpu, 0, 0x2000, this->low_ram, low_ram_size ); // mirrored four times
338 Cpu_map_code( &this->cpu, sram_addr, sram_size, sram( this ), 0 );
340 // Determine initial banks
341 byte banks [bank_count];
342 static byte const zero_banks [sizeof this->header.banks] = { 0 };
343 if ( memcmp( this->header.banks, zero_banks, sizeof zero_banks ) )
345 banks [0] = this->header.banks [6];
346 banks [1] = this->header.banks [7];
347 memcpy( banks + fds_banks, this->header.banks, sizeof this->header.banks );
349 else
351 // No initial banks, so assign them based on load_addr
352 int i, first_bank = (get_addr( this->header.load_addr ) - sram_addr) / this->rom.bank_size;
353 unsigned total_banks = this->rom.size / this->rom.bank_size;
354 for ( i = bank_count; --i >= 0; )
356 int bank = i - first_bank;
357 if ( (unsigned) bank >= total_banks )
358 bank = 0;
359 banks [i] = bank;
363 // Map banks
364 int i;
365 for ( i = (fds_enabled( this ) ? 0 : fds_banks); i < bank_count; ++i )
366 write_bank( this, i, banks [i] );
368 // Map FDS RAM
369 if ( fds_enabled( this ) )
370 Cpu_map_code( &this->cpu, rom_addr, fdsram_size, fdsram( this ), 0 );
373 void set_voice( struct Nsf_Emu* this, int i, struct Blip_Buffer* buf, struct Blip_Buffer* left, struct Blip_Buffer* right)
375 #if defined(ROCKBOX)
376 (void) left;
377 (void) right;
378 #endif
380 if ( i < apu_osc_count )
382 Apu_osc_output( &this->apu, i, buf );
383 return;
385 i -= apu_osc_count;
387 #ifndef NSF_EMU_APU_ONLY
389 if ( vrc6_enabled( this ) && (i -= vrc6_osc_count) < 0 )
391 Vrc6_osc_output( &this->vrc6, i + vrc6_osc_count, buf );
392 return;
395 if ( fme7_enabled( this ) && (i -= fme7_osc_count) < 0 )
397 Fme7_osc_output( &this->fme7, i + fme7_osc_count, buf );
398 return;
401 if ( mmc5_enabled( this ) && (i -= mmc5_osc_count) < 0 )
403 Mmc5_set_output( &this->mmc5, i + mmc5_osc_count, buf );
404 return;
407 if ( fds_enabled( this ) && (i -= fds_osc_count) < 0 )
409 Fds_set_output( &this->fds, i + fds_osc_count, buf );
410 return;
413 if ( namco_enabled( this ) && (i -= namco_osc_count) < 0 )
415 Namco_osc_output( &this->namco, i + namco_osc_count, buf );
416 return;
419 if ( vrc7_enabled( this ) && (i -= vrc7_osc_count) < 0 )
421 Vrc7_set_output( &this->vrc7, i + vrc7_osc_count, buf );
422 return;
425 #endif
428 // Emulation
430 // Music Emu
432 blargg_err_t Nsf_set_sample_rate( struct Nsf_Emu* this, long rate )
434 require( !this->sample_rate ); // sample rate can't be changed once set
435 Buffer_init( &this->stereo_buf );
436 RETURN_ERR( Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 ) );
438 // Set bass frequency
439 Buffer_bass_freq( &this->stereo_buf, 80 );
441 this->sample_rate = rate;
442 return 0;
445 void Sound_mute_voice( struct Nsf_Emu* this, int index, bool mute )
447 require( (unsigned) index < (unsigned) this->voice_count );
448 int bit = 1 << index;
449 int mask = this->mute_mask_ | bit;
450 if ( !mute )
451 mask ^= bit;
452 Sound_mute_voices( this, mask );
455 void Sound_mute_voices( struct Nsf_Emu* this, int mask )
457 require( this->sample_rate ); // sample rate must be set first
458 this->mute_mask_ = mask;
460 int i;
461 for ( i = this->voice_count; i--; )
463 if ( mask & (1 << i) )
465 set_voice( this, i, 0, 0, 0 );
467 else
469 struct channel_t ch = Buffer_channel( &this->stereo_buf );
470 assert( (ch.center && ch.left && ch.right) ||
471 (!ch.center && !ch.left && !ch.right) ); // all or nothing
472 set_voice( this, i, ch.center, ch.left, ch.right );
477 void Sound_set_tempo( struct Nsf_Emu* this, double t )
479 require( this->sample_rate ); // sample rate must be set first
480 double const min = 0.02;
481 double const max = 4.00;
482 if ( t < min ) t = min;
483 if ( t > max ) t = max;
484 this->tempo = t;
486 set_play_period( this, (int) (play_period( &this->header ) / t) );
488 Apu_set_tempo( &this->apu, t );
490 #ifndef NSF_EMU_APU_ONLY
491 if ( fds_enabled( this ) )
492 Fds_set_tempo( &this->fds, t );
493 #endif
496 inline void push_byte( struct Nsf_Emu* this, int b )
498 this->low_ram [0x100 + this->cpu.r.sp--] = b;
501 // Jumps to routine, given pointer to address in file header. Pushes idle_addr
502 // as return address, NOT old PC.
503 void jsr_then_stop( struct Nsf_Emu* this, byte const addr [] )
505 this->cpu.r.pc = get_addr( addr );
506 push_byte( this, (idle_addr - 1) >> 8 );
507 push_byte( this, (idle_addr - 1) );
510 int cpu_read( struct Nsf_Emu* this, addr_t addr )
512 #ifndef NSF_EMU_APU_ONLY
514 if ( namco_enabled( this ) && addr == namco_data_reg_addr )
515 return Namco_read_data( &this->namco );
517 if ( fds_enabled( this ) && (unsigned) (addr - fds_io_addr) < fds_io_size )
518 return Fds_read( &this->fds, Cpu_time( &this->cpu ), addr );
520 if ( mmc5_enabled( this ) ) {
521 int i = addr - 0x5C00;
522 if ( (unsigned) i < mmc5_exram_size )
523 return this->mmc5.exram [i];
525 int m = addr - 0x5205;
526 if ( (unsigned) m < 2 )
527 return (this->mmc5_mul [0] * this->mmc5_mul [1]) >> (m * 8) & 0xFF;
530 #endif
532 /* Unmapped read */
533 return addr >> 8;
536 int unmapped_read( struct Nsf_Emu* this, addr_t addr )
538 (void) this;
540 switch ( addr )
542 case 0x2002:
543 case 0x4016:
544 case 0x4017:
545 return addr >> 8;
548 // Unmapped read
549 return addr >> 8;
552 void cpu_write( struct Nsf_Emu* this, addr_t addr, int data )
554 #ifndef NSF_EMU_APU_ONLY
556 nes_time_t time = Cpu_time( &this->cpu );
557 if ( fds_enabled( this) && (unsigned) (addr - fds_io_addr) < fds_io_size )
559 Fds_write( &this->fds, time, addr, data );
560 return;
563 if ( namco_enabled( this) )
565 if ( addr == namco_addr_reg_addr )
567 Namco_write_addr( &this->namco, data );
568 return;
571 if ( addr == namco_data_reg_addr )
573 Namco_write_data( &this->namco, time, data );
574 return;
578 if ( vrc6_enabled( this) )
580 int reg = addr & (vrc6_addr_step - 1);
581 int osc = (unsigned) (addr - vrc6_base_addr) / vrc6_addr_step;
582 if ( (unsigned) osc < vrc6_osc_count && (unsigned) reg < vrc6_reg_count )
584 Vrc6_write_osc( &this->vrc6, time, osc, reg, data );
585 return;
589 if ( fme7_enabled( this) && addr >= fme7_latch_addr )
591 switch ( addr & fme7_addr_mask )
593 case fme7_latch_addr:
594 Fme7_write_latch( &this->fme7, data );
595 return;
597 case fme7_data_addr:
598 Fme7_write_data( &this->fme7, time, data );
599 return;
603 if ( mmc5_enabled( this) )
605 if ( (unsigned) (addr - mmc5_regs_addr) < mmc5_regs_size )
607 Mmc5_write_register( &this->mmc5, time, addr, data );
608 return;
611 int m = addr - 0x5205;
612 if ( (unsigned) m < 2 )
614 this->mmc5_mul [m] = data;
615 return;
618 int i = addr - 0x5C00;
619 if ( (unsigned) i < mmc5_exram_size )
621 this->mmc5.exram [i] = data;
622 return;
626 if ( vrc7_enabled( this) )
628 if ( addr == 0x9010 )
630 Vrc7_write_reg( &this->vrc7, data );
631 return;
634 if ( (unsigned) (addr - 0x9028) <= 0x08 )
636 Vrc7_write_data( &this->vrc7, time, data );
637 return;
641 #endif
643 // Unmapped_write
646 void unmapped_write( struct Nsf_Emu* this, addr_t addr, int data )
648 (void) data;
650 switch ( addr )
652 case 0x8000: // some write to $8000 and $8001 repeatedly
653 case 0x8001:
654 case 0x4800: // probably namco sound mistakenly turned on in MCK
655 case 0xF800:
656 case 0xFFF8: // memory mapper?
657 return;
660 if ( mmc5_enabled( this ) && addr == 0x5115 ) return;
662 // FDS memory
663 if ( fds_enabled( this ) && (unsigned) (addr - 0x8000) < 0x6000 ) return;
666 void fill_buf( struct Nsf_Emu* this );
667 blargg_err_t Nsf_start_track( struct Nsf_Emu* this, int track )
669 clear_track_vars( this );
671 // Remap track if playlist available
672 if ( this->m3u.size > 0 ) {
673 struct entry_t* e = &this->m3u.entries[track];
674 track = e->track;
676 else track = Info_remap_track( &this->info, track );
678 this->current_track = track;
679 Buffer_clear( &this->stereo_buf );
681 #ifndef NSF_EMU_APU_ONLY
682 if ( mmc5_enabled( this ) )
684 this->mmc5_mul [0] = 0;
685 this->mmc5_mul [1] = 0;
686 memset( this->mmc5.exram, 0, mmc5_exram_size );
689 if ( fds_enabled( this ) ) Fds_reset( &this->fds );
690 if ( namco_enabled( this ) ) Namco_reset( &this->namco );
691 if ( vrc6_enabled( this ) ) Vrc6_reset( &this->vrc6 );
692 if ( fme7_enabled( this ) ) Fme7_reset( &this->fme7 );
693 if ( mmc5_enabled( this ) ) Apu_reset( &this->mmc5.apu, false, 0 );
694 if ( vrc7_enabled( this ) ) Vrc7_reset( &this->vrc7 );
695 #endif
697 int speed_flags = 0;
698 #ifdef NSF_EMU_EXTRA_FLAGS
699 speed_flags = this->header.speed_flags;
700 #endif
702 Apu_reset( &this->apu, pal_only( &this->header ), (speed_flags & 0x20) ? 0x3F : 0 );
703 Apu_write_register( &this->apu, 0, 0x4015, 0x0F );
704 Apu_write_register( &this->apu, 0, 0x4017, (speed_flags & 0x10) ? 0x80 : 0 );
706 memset( unmapped_code( this ), halt_opcode, unmapped_size );
707 memset( this->low_ram, 0, low_ram_size );
708 memset( sram( this ), 0, sram_size );
710 map_memory( this );
712 // Arrange time of first call to play routine
713 this->play_extra = 0;
714 this->next_play = this->play_period;
716 this->play_delay = initial_play_delay;
717 this->saved_state.pc = idle_addr;
719 // Setup for call to init routine
720 this->cpu.r.a = track;
721 this->cpu.r.x = pal_only( &this->header );
722 this->cpu.r.sp = 0xFF;
723 jsr_then_stop( this, this->header.init_addr );
724 /* if ( this->cpu.r.pc < get_addr( header.load_addr ) )
725 warning( "Init address < load address" ); */
727 this->emu_track_ended_ = false;
728 this->track_ended = false;
730 if ( !this->ignore_silence )
732 // play until non-silence or end of track
733 long end;
734 for ( end = this->max_initial_silence * stereo * this->sample_rate; this->emu_time < end; )
736 fill_buf( this );
737 if ( this->buf_remain | (int) this->emu_track_ended_ )
738 break;
741 this->emu_time = this->buf_remain;
742 this->out_time = 0;
743 this->silence_time = 0;
744 this->silence_count = 0;
746 /* return track_ended() ? warning() : 0; */
747 return 0;
750 void run_once( struct Nsf_Emu* this, nes_time_t end )
752 // Emulate until next play call if possible
753 if ( run_cpu_until( this, min( this->next_play, end ) ) )
755 // Halt instruction encountered
757 if ( this->cpu.r.pc != idle_addr )
759 // special_event( "illegal instruction" );
760 Cpu_set_time( &this->cpu, this->cpu.end_time );
761 return;
764 // Init/play routine returned
765 this->play_delay = 1; // play can now be called regularly
767 if ( this->saved_state.pc == idle_addr )
769 // nothing to run
770 nes_time_t t = this->cpu.end_time;
771 if ( Cpu_time( &this->cpu ) < t )
772 Cpu_set_time( &this->cpu, t );
774 else
776 // continue init routine that was interrupted by play routine
777 this->cpu.r = this->saved_state;
778 this->saved_state.pc = idle_addr;
782 if ( Cpu_time( &this->cpu ) >= this->next_play )
784 // Calculate time of next call to play routine
785 this->play_extra ^= 1; // extra clock every other call
786 this->next_play += this->play_period + this->play_extra;
788 // Call routine if ready
789 if ( this->play_delay && !--this->play_delay )
791 // Save state if init routine is still running
792 if ( this->cpu.r.pc != idle_addr )
794 check( this->saved_state.pc == idle_addr );
795 this->saved_state = this->cpu.r;
796 // special_event( "play called during init" );
799 jsr_then_stop( this, this->header.play_addr );
804 void run_until( struct Nsf_Emu* this, nes_time_t end )
806 while ( Cpu_time( &this->cpu ) < end )
807 run_once( this, end );
810 void end_frame( struct Nsf_Emu* this, nes_time_t end )
812 if ( Cpu_time( &this->cpu ) < end )
813 run_until( this, end );
814 Cpu_adjust_time( &this->cpu, -end );
816 // Localize to new time frame
817 this->next_play -= end;
818 check( this->next_play >= 0 );
819 if ( this->next_play < 0 )
820 this->next_play = 0;
822 Apu_end_frame( &this->apu, end );
824 #ifndef NSF_EMU_APU_ONLY
825 if ( fds_enabled( this ) ) Fds_end_frame( &this->fds, end );
826 if ( fme7_enabled( this ) ) Fme7_end_frame( &this->fme7, end );
827 if ( mmc5_enabled( this ) ) Apu_end_frame( &this->mmc5.apu, end );
828 if ( namco_enabled( this ) ) Namco_end_frame( &this->namco, end );
829 if ( vrc6_enabled( this ) ) Vrc6_end_frame( &this->vrc6, end );
830 if ( vrc7_enabled( this ) ) Vrc7_end_frame( &this->vrc7, end );
831 #endif
834 // Tell/Seek
836 blargg_long msec_to_samples( long sample_rate, blargg_long msec )
838 blargg_long sec = msec / 1000;
839 msec -= sec * 1000;
840 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
843 long Track_tell( struct Nsf_Emu* this )
845 blargg_long rate = this->sample_rate * stereo;
846 blargg_long sec = this->out_time / rate;
847 return sec * 1000 + (this->out_time - sec * rate) * 1000 / rate;
850 blargg_err_t Track_seek( struct Nsf_Emu* this, long msec )
852 blargg_long time = msec_to_samples( this->sample_rate, msec );
853 if ( time < this->out_time )
854 RETURN_ERR( Nsf_start_track( this, this->current_track ) );
855 return Track_skip( this, time - this->out_time );
858 blargg_err_t skip_( struct Nsf_Emu* this, long count ) ICODE_ATTR;
859 blargg_err_t Track_skip( struct Nsf_Emu* this, long count )
861 require( this->current_track >= 0 ); // start_track() must have been called already
862 this->out_time += count;
864 // remove from silence and buf first
866 long n = min( count, this->silence_count );
867 this->silence_count -= n;
868 count -= n;
870 n = min( count, this->buf_remain );
871 this->buf_remain -= n;
872 count -= n;
875 if ( count && !this->emu_track_ended_ )
877 this->emu_time += count;
878 // End track if error
879 if ( skip_( this, count ) )
880 this->emu_track_ended_ = true;
883 if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended
884 this->track_ended |= this->emu_track_ended_;
886 return 0;
889 blargg_err_t play_( struct Nsf_Emu* this, long count, sample_t* out ) ICODE_ATTR;
890 blargg_err_t skip_( struct Nsf_Emu* this, long count )
892 // for long skip, mute sound
893 const long threshold = 30000;
894 if ( count > threshold )
896 int saved_mute = this->mute_mask_;
897 Sound_mute_voices( this, ~0 );
899 while ( count > threshold / 2 && !this->emu_track_ended_ )
901 RETURN_ERR( play_( this, buf_size, this->buf ) );
902 count -= buf_size;
905 Sound_mute_voices( this, saved_mute );
908 while ( count && !this->emu_track_ended_ )
910 long n = buf_size;
911 if ( n > count )
912 n = count;
913 count -= n;
914 RETURN_ERR( play_( this, n, this->buf ) );
916 return 0;
919 // Fading
921 void Track_set_fade( struct Nsf_Emu* this, long start_msec, long length_msec )
923 this->fade_step = this->sample_rate * length_msec / (fade_block_size * fade_shift * 1000 / stereo);
924 this->fade_start = msec_to_samples( this->sample_rate, start_msec );
927 // unit / pow( 2.0, (double) x / step )
928 static int int_log( blargg_long x, int step, int unit )
930 int shift = x / step;
931 int fraction = (x - shift * step) * unit / step;
932 return ((unit - fraction) + (fraction >> 1)) >> shift;
935 void handle_fade( struct Nsf_Emu* this, long out_count, sample_t* out )
937 int i;
938 for ( i = 0; i < out_count; i += fade_block_size )
940 int const shift = 14;
941 int const unit = 1 << shift;
942 int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size,
943 this->fade_step, unit );
944 if ( gain < (unit >> fade_shift) )
945 this->track_ended = this->emu_track_ended_ = true;
947 sample_t* io = &out [i];
948 int count;
949 for ( count = min( fade_block_size, out_count - i ); count; --count )
951 *io = (sample_t) ((*io * gain) >> shift);
952 ++io;
957 // Silence detection
959 void emu_play( struct Nsf_Emu* this, long count, sample_t* out ) ICODE_ATTR;
960 void emu_play( struct Nsf_Emu* this, long count, sample_t* out )
962 check( current_track_ >= 0 );
963 this->emu_time += count;
964 if ( this->current_track >= 0 && !this->emu_track_ended_ ) {
966 // End track if error
967 if ( play_( this, count, out ) )
968 this->emu_track_ended_ = true;
970 else
971 memset( out, 0, count * sizeof *out );
974 // number of consecutive silent samples at end
975 static long count_silence( sample_t* begin, long size )
977 sample_t first = *begin;
978 *begin = silence_threshold; // sentinel
979 sample_t* p = begin + size;
980 while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
981 *begin = first;
982 return size - (p - begin);
985 // fill internal buffer and check it for silence
986 void fill_buf( struct Nsf_Emu* this )
988 assert( !this->buf_remain );
989 if ( !this->emu_track_ended_ )
991 emu_play( this, buf_size, this->buf );
992 long silence = count_silence( this->buf, buf_size );
993 if ( silence < buf_size )
995 this->silence_time = this->emu_time - silence;
996 this->buf_remain = buf_size;
997 return;
1000 this->silence_count += buf_size;
1003 blargg_err_t Nsf_play( struct Nsf_Emu* this, long out_count, sample_t* out )
1005 if ( this->track_ended )
1007 memset( out, 0, out_count * sizeof *out );
1009 else
1011 require( this->current_track >= 0 );
1012 require( out_count % stereo == 0 );
1014 assert( this->emu_time >= this->out_time );
1016 long pos = 0;
1017 if ( this->silence_count )
1019 // during a run of silence, run emulator at >=2x speed so it gets ahead
1020 long ahead_time = this->silence_lookahead * (this->out_time + out_count - this->silence_time) + this->silence_time;
1021 while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) )
1022 fill_buf( this );
1024 // fill with silence
1025 pos = min( this->silence_count, out_count );
1026 memset( out, 0, pos * sizeof *out );
1027 this->silence_count -= pos;
1029 if ( this->emu_time - this->silence_time > silence_max * stereo * this->sample_rate )
1031 this->track_ended = this->emu_track_ended_ = true;
1032 this->silence_count = 0;
1033 this->buf_remain = 0;
1037 if ( this->buf_remain )
1039 // empty silence buf
1040 long n = min( this->buf_remain, out_count - pos );
1041 memcpy( &out [pos], this->buf + (buf_size - this->buf_remain), n * sizeof *out );
1042 this->buf_remain -= n;
1043 pos += n;
1046 // generate remaining samples normally
1047 long remain = out_count - pos;
1048 if ( remain )
1050 emu_play( this, remain, out + pos );
1051 this->track_ended |= this->emu_track_ended_;
1053 if ( !this->ignore_silence || this->out_time > this->fade_start )
1055 // check end for a new run of silence
1056 long silence = count_silence( out + pos, remain );
1057 if ( silence < remain )
1058 this->silence_time = this->emu_time - silence;
1060 if ( this->emu_time - this->silence_time >= buf_size )
1061 fill_buf( this ); // cause silence detection on next play()
1065 if ( this->out_time > this->fade_start )
1066 handle_fade( this, out_count, out );
1068 this->out_time += out_count;
1069 return 0;
1072 blargg_err_t play_( struct Nsf_Emu* this, long count, sample_t* out )
1074 long remain = count;
1075 while ( remain )
1077 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
1078 if ( remain )
1080 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
1082 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
1084 // Remute voices
1085 Sound_mute_voices( this, this->mute_mask_ );
1087 int msec = Buffer_length( &this->stereo_buf );
1088 blip_time_t clocks_emulated = (blargg_long) msec * this->clock_rate__ / 1000 - 100;
1089 RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) );
1090 assert( clocks_emulated );
1091 Buffer_end_frame( &this->stereo_buf, clocks_emulated );
1094 return 0;
1097 blargg_err_t run_clocks( struct Nsf_Emu* this, blip_time_t* duration, int msec )
1099 #if defined(ROCKBOX)
1100 (void) msec;
1101 #endif
1103 end_frame( this, *duration );
1104 return 0;