summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndree Buschmann <AndreeBuschmann@t-online.de>2011-08-31 19:19:49 +0000
committerAndree Buschmann <AndreeBuschmann@t-online.de>2011-08-31 19:19:49 +0000
commit13cbade08a07296d92e7a7d3e20475de0032cba1 (patch)
tree731a1a4a99d86632a719ae49e3b3d2a12e764a3a
parentd089e104034fdf5562bea125d2cacf4ee486782a (diff)
downloadrockbox-13cbade08a07296d92e7a7d3e20475de0032cba1.tar.gz
rockbox-13cbade08a07296d92e7a7d3e20475de0032cba1.zip
Update libgme to Blargg's Game_Music_Emu 0.6-pre.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30397 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs/ay.c4
-rw-r--r--apps/codecs/gbs.c6
-rw-r--r--apps/codecs/hes.c6
-rw-r--r--apps/codecs/kss.c2
-rw-r--r--apps/codecs/libgme/AYSOURCES1
-rw-r--r--apps/codecs/libgme/GBSSOURCES1
-rw-r--r--apps/codecs/libgme/HESSOURCES1
-rw-r--r--apps/codecs/libgme/KSSSOURCES1
-rw-r--r--apps/codecs/libgme/NSFSOURCES1
-rw-r--r--apps/codecs/libgme/SGCSOURCES1
-rw-r--r--apps/codecs/libgme/VGMSOURCES1
-rw-r--r--apps/codecs/libgme/ay_emu.c356
-rw-r--r--apps/codecs/libgme/ay_emu.h71
-rw-r--r--apps/codecs/libgme/blargg_common.h22
-rw-r--r--apps/codecs/libgme/blargg_endian.h77
-rw-r--r--apps/codecs/libgme/blargg_source.h39
-rw-r--r--apps/codecs/libgme/blip_buffer.c237
-rw-r--r--apps/codecs/libgme/blip_buffer.h342
-rw-r--r--apps/codecs/libgme/gbs_cpu.c32
-rw-r--r--apps/codecs/libgme/gbs_emu.c355
-rw-r--r--apps/codecs/libgme/gbs_emu.h82
-rw-r--r--apps/codecs/libgme/gme_types.h21
-rw-r--r--apps/codecs/libgme/hes_apu.c306
-rw-r--r--apps/codecs/libgme/hes_apu.h43
-rw-r--r--apps/codecs/libgme/hes_apu_adpcm.h4
-rw-r--r--apps/codecs/libgme/hes_cpu.c1356
-rw-r--r--apps/codecs/libgme/hes_cpu.h119
-rw-r--r--apps/codecs/libgme/hes_cpu_io.h72
-rw-r--r--apps/codecs/libgme/hes_cpu_run.h1344
-rw-r--r--apps/codecs/libgme/hes_emu.c581
-rw-r--r--apps/codecs/libgme/hes_emu.h156
-rw-r--r--apps/codecs/libgme/kss_emu.c373
-rw-r--r--apps/codecs/libgme/kss_emu.h69
-rw-r--r--apps/codecs/libgme/kss_scc_apu.h2
-rw-r--r--apps/codecs/libgme/multi_buffer.c390
-rw-r--r--apps/codecs/libgme/multi_buffer.h108
-rw-r--r--apps/codecs/libgme/nes_apu.c24
-rw-r--r--apps/codecs/libgme/nes_apu.h43
-rw-r--r--apps/codecs/libgme/nes_cpu_io.h94
-rw-r--r--apps/codecs/libgme/nes_fme7_apu.c7
-rw-r--r--apps/codecs/libgme/nes_fme7_apu.h2
-rw-r--r--apps/codecs/libgme/nes_namco_apu.c15
-rw-r--r--apps/codecs/libgme/nes_namco_apu.h4
-rw-r--r--apps/codecs/libgme/nes_oscs.c73
-rw-r--r--apps/codecs/libgme/nes_oscs.h18
-rw-r--r--apps/codecs/libgme/nes_vrc6_apu.c2
-rw-r--r--apps/codecs/libgme/nes_vrc6_apu.h4
-rw-r--r--apps/codecs/libgme/nsf_emu.c496
-rw-r--r--apps/codecs/libgme/nsf_emu.h104
-rw-r--r--apps/codecs/libgme/nsfe_info.c10
-rw-r--r--apps/codecs/libgme/opl_apu.h4
-rw-r--r--apps/codecs/libgme/resampler.c22
-rw-r--r--apps/codecs/libgme/resampler.h13
-rw-r--r--apps/codecs/libgme/rom_data.c8
-rw-r--r--apps/codecs/libgme/rom_data.h28
-rw-r--r--apps/codecs/libgme/sgc_emu.c319
-rw-r--r--apps/codecs/libgme/sgc_emu.h76
-rw-r--r--apps/codecs/libgme/sms_apu.c4
-rw-r--r--apps/codecs/libgme/sms_apu.h4
-rw-r--r--apps/codecs/libgme/sms_fm_apu.h8
-rw-r--r--apps/codecs/libgme/track_filter.c294
-rw-r--r--apps/codecs/libgme/track_filter.h90
-rw-r--r--apps/codecs/libgme/vgm_emu.c388
-rw-r--r--apps/codecs/libgme/vgm_emu.h103
-rw-r--r--apps/codecs/libgme/ym2612_emu.c1
-rw-r--r--apps/codecs/nsf.c6
-rw-r--r--apps/codecs/sgc.c4
-rw-r--r--apps/codecs/vgm.c2
68 files changed, 4036 insertions, 4816 deletions
diff --git a/apps/codecs/ay.c b/apps/codecs/ay.c
index 914ffa9803..b11ad84294 100644
--- a/apps/codecs/ay.c
+++ b/apps/codecs/ay.c
@@ -74,7 +74,7 @@ enum codec_status codec_run(void)
74 } 74 }
75 75
76 if ((err = Ay_load_mem(&ay_emu, buf, ci->filesize))) { 76 if ((err = Ay_load_mem(&ay_emu, buf, ci->filesize))) {
77 DEBUGF("AY: Ay_load failed (%s)\n", err); 77 DEBUGF("AY: Ay_load_mem failed (%s)\n", err);
78 return CODEC_ERROR; 78 return CODEC_ERROR;
79 } 79 }
80 80
@@ -118,7 +118,7 @@ next_track:
118 118
119 /* Generate audio buffer */ 119 /* Generate audio buffer */
120 err = Ay_play(&ay_emu, CHUNK_SIZE, samples); 120 err = Ay_play(&ay_emu, CHUNK_SIZE, samples);
121 if (err || ay_emu.track_ended) { 121 if (err || Track_ended(&ay_emu)) {
122 track++; 122 track++;
123 if (track >= ay_emu.track_count) break; 123 if (track >= ay_emu.track_count) break;
124 goto next_track; 124 goto next_track;
diff --git a/apps/codecs/gbs.c b/apps/codecs/gbs.c
index c9c3420683..def05ed351 100644
--- a/apps/codecs/gbs.c
+++ b/apps/codecs/gbs.c
@@ -67,8 +67,8 @@ enum codec_status codec_run(void)
67 return CODEC_ERROR; 67 return CODEC_ERROR;
68 } 68 }
69 69
70 if ((err = Gbs_load(&gbs_emu, buf, ci->filesize))) { 70 if ((err = Gbs_load_mem(&gbs_emu, buf, ci->filesize))) {
71 DEBUGF("GBS: Gbs_load failed (%s)\n", err); 71 DEBUGF("GBS: Gbs_load_mem failed (%s)\n", err);
72 return CODEC_ERROR; 72 return CODEC_ERROR;
73 } 73 }
74 74
@@ -95,7 +95,7 @@ next_track:
95 95
96 /* Generate audio buffer */ 96 /* Generate audio buffer */
97 err = Gbs_play(&gbs_emu, CHUNK_SIZE, samples); 97 err = Gbs_play(&gbs_emu, CHUNK_SIZE, samples);
98 if (err || gbs_emu.track_ended) { 98 if (err || Track_ended(&gbs_emu)) {
99 track++; 99 track++;
100 if (track >= gbs_emu.track_count) break; 100 if (track >= gbs_emu.track_count) break;
101 goto next_track; 101 goto next_track;
diff --git a/apps/codecs/hes.c b/apps/codecs/hes.c
index c84134c01b..849fd88f12 100644
--- a/apps/codecs/hes.c
+++ b/apps/codecs/hes.c
@@ -67,8 +67,8 @@ enum codec_status codec_run(void)
67 return CODEC_ERROR; 67 return CODEC_ERROR;
68 } 68 }
69 69
70 if ((err = Hes_load(&hes_emu, buf, ci->filesize))) { 70 if ((err = Hes_load_mem(&hes_emu, buf, ci->filesize))) {
71 DEBUGF("HES: Hes_load failed (%s)\n", err); 71 DEBUGF("HES: Hes_load_mem failed (%s)\n", err);
72 return CODEC_ERROR; 72 return CODEC_ERROR;
73 } 73 }
74 74
@@ -95,7 +95,7 @@ next_track:
95 95
96 /* Generate audio buffer */ 96 /* Generate audio buffer */
97 err = Hes_play(&hes_emu, CHUNK_SIZE, samples); 97 err = Hes_play(&hes_emu, CHUNK_SIZE, samples);
98 if (err || hes_emu.track_ended) { 98 if (err || Track_ended(&hes_emu)) {
99 track++; 99 track++;
100 if (track >= hes_emu.track_count) break; 100 if (track >= hes_emu.track_count) break;
101 goto next_track; 101 goto next_track;
diff --git a/apps/codecs/kss.c b/apps/codecs/kss.c
index f519b3c706..92efcd4e5f 100644
--- a/apps/codecs/kss.c
+++ b/apps/codecs/kss.c
@@ -98,7 +98,7 @@ next_track:
98 98
99 /* Generate audio buffer */ 99 /* Generate audio buffer */
100 err = Kss_play(&kss_emu, CHUNK_SIZE, samples); 100 err = Kss_play(&kss_emu, CHUNK_SIZE, samples);
101 if (err || kss_emu.track_ended) { 101 if (err || Track_ended(&kss_emu)) {
102 track++; 102 track++;
103 if (track >= kss_emu.track_count) break; 103 if (track >= kss_emu.track_count) break;
104 goto next_track; 104 goto next_track;
diff --git a/apps/codecs/libgme/AYSOURCES b/apps/codecs/libgme/AYSOURCES
index 51253fe2f1..f2b52a51d9 100644
--- a/apps/codecs/libgme/AYSOURCES
+++ b/apps/codecs/libgme/AYSOURCES
@@ -3,4 +3,5 @@ ay_cpu.c
3ay_emu.c 3ay_emu.c
4blip_buffer.c 4blip_buffer.c
5multi_buffer.c 5multi_buffer.c
6track_filter.c
6z80_cpu.c 7z80_cpu.c
diff --git a/apps/codecs/libgme/GBSSOURCES b/apps/codecs/libgme/GBSSOURCES
index 5548fd85eb..a839a2156e 100644
--- a/apps/codecs/libgme/GBSSOURCES
+++ b/apps/codecs/libgme/GBSSOURCES
@@ -6,3 +6,4 @@ gbs_emu.c
6blip_buffer.c 6blip_buffer.c
7multi_buffer.c 7multi_buffer.c
8rom_data.c 8rom_data.c
9track_filter.c
diff --git a/apps/codecs/libgme/HESSOURCES b/apps/codecs/libgme/HESSOURCES
index 58a38f2f5a..d529388978 100644
--- a/apps/codecs/libgme/HESSOURCES
+++ b/apps/codecs/libgme/HESSOURCES
@@ -5,3 +5,4 @@ hes_emu.c
5blip_buffer.c 5blip_buffer.c
6multi_buffer.c 6multi_buffer.c
7rom_data.c 7rom_data.c
8track_filter.c
diff --git a/apps/codecs/libgme/KSSSOURCES b/apps/codecs/libgme/KSSSOURCES
index 2607c7364c..bde213364b 100644
--- a/apps/codecs/libgme/KSSSOURCES
+++ b/apps/codecs/libgme/KSSSOURCES
@@ -9,3 +9,4 @@ multi_buffer.c
9rom_data.c 9rom_data.c
10emu8950.c 10emu8950.c
11emuadpcm.c 11emuadpcm.c
12track_filter.c
diff --git a/apps/codecs/libgme/NSFSOURCES b/apps/codecs/libgme/NSFSOURCES
index 54b4f82f60..60537ff8e4 100644
--- a/apps/codecs/libgme/NSFSOURCES
+++ b/apps/codecs/libgme/NSFSOURCES
@@ -12,3 +12,4 @@ nsfe_info.c
12blip_buffer.c 12blip_buffer.c
13multi_buffer.c 13multi_buffer.c
14rom_data.c 14rom_data.c
15track_filter.c
diff --git a/apps/codecs/libgme/SGCSOURCES b/apps/codecs/libgme/SGCSOURCES
index d91c0e1731..d0e8abc2b7 100644
--- a/apps/codecs/libgme/SGCSOURCES
+++ b/apps/codecs/libgme/SGCSOURCES
@@ -4,3 +4,4 @@ z80_cpu.c
4blip_buffer.c 4blip_buffer.c
5multi_buffer.c 5multi_buffer.c
6rom_data.c 6rom_data.c
7track_filter.c
diff --git a/apps/codecs/libgme/VGMSOURCES b/apps/codecs/libgme/VGMSOURCES
index 637f87e8b0..bb57e16e82 100644
--- a/apps/codecs/libgme/VGMSOURCES
+++ b/apps/codecs/libgme/VGMSOURCES
@@ -3,6 +3,7 @@ multi_buffer.c
3resampler.c 3resampler.c
4vgm_emu.c 4vgm_emu.c
5ym2612_emu.c 5ym2612_emu.c
6track_filter.c
6inflate/bbfuncs.c 7inflate/bbfuncs.c
7inflate/inflate.c 8inflate/inflate.c
8inflate/mallocer.c 9inflate/mallocer.c
diff --git a/apps/codecs/libgme/ay_emu.c b/apps/codecs/libgme/ay_emu.c
index e961797dd3..42e739f2df 100644
--- a/apps/codecs/libgme/ay_emu.c
+++ b/apps/codecs/libgme/ay_emu.c
@@ -17,12 +17,6 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
17 17
18#include "blargg_source.h" 18#include "blargg_source.h"
19 19
20int const stereo = 2; // number of channels for stereo
21int const silence_max = 6; // seconds
22int const silence_threshold = 0x10;
23long const fade_block_size = 512;
24int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
25
26const char* const gme_wrong_file_type = "Wrong file type for this emulator"; 20const char* const gme_wrong_file_type = "Wrong file type for this emulator";
27 21
28// TODO: probably don't need detailed errors as to why file is corrupt 22// TODO: probably don't need detailed errors as to why file is corrupt
@@ -38,16 +32,7 @@ int const cpc_clock = 2000000;
38static void clear_track_vars( struct Ay_Emu *this ) 32static void clear_track_vars( struct Ay_Emu *this )
39{ 33{
40 this->current_track = -1; 34 this->current_track = -1;
41 this->out_time = 0; 35 track_stop( &this->track_filter );
42 this->emu_time = 0;
43 this->emu_track_ended_ = true;
44 this->track_ended = true;
45 this->fade_start = INT_MAX / 2 + 1;
46 this->fade_step = 1;
47 this->silence_time = 0;
48 this->silence_count = 0;
49 this->buf_remain = 0;
50 /* warning(); // clear warning */
51} 36}
52 37
53void Ay_init( struct Ay_Emu *this ) 38void Ay_init( struct Ay_Emu *this )
@@ -59,18 +44,21 @@ void Ay_init( struct Ay_Emu *this )
59 this->track_count = 0; 44 this->track_count = 0;
60 45
61 // defaults 46 // defaults
62 this->max_initial_silence = 2; 47 this->tfilter = *track_get_setup( &this->track_filter );
63 this->ignore_silence = false; 48 this->tfilter.max_initial = 2;
49 this->tfilter.lookahead = 6;
50 this->track_filter.silence_ignored_ = false;
64 51
65 this->voice_count = 0;
66 clear_track_vars( this );
67 this->beeper_output = NULL; 52 this->beeper_output = NULL;
68 disable_beeper( this ); 53 disable_beeper( this );
69 54
70 Ay_apu_init( &this->apu ); 55 Ay_apu_init( &this->apu );
71 Z80_init( &this->cpu ); 56 Z80_init( &this->cpu );
72 57
73 this->silence_lookahead = 6 ; 58 // clears fields
59 this->voice_count = 0;
60 this->voice_types = 0;
61 clear_track_vars( this );
74} 62}
75 63
76// Track info 64// Track info
@@ -107,35 +95,22 @@ static blargg_err_t parse_header( byte const in [], int size, struct file_t* out
107 return 0; 95 return 0;
108} 96}
109 97
110long Track_get_length( struct Ay_Emu* this, int n )
111{
112 long length = 0;
113
114 byte const* track_info = get_data( &this->file, this->file.tracks + n * 4 + 2, 6 );
115 if ( track_info )
116 length = get_be16( track_info + 4 ) * (1000 / 50); // frames to msec
117
118 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
119 struct entry_t* entry = &this->m3u.entries [n];
120 length = entry->length;
121 }
122
123 if ( length <= 0 )
124 length = 120 * 1000; /* 2 minutes */
125
126 return length;
127}
128
129// Setup 98// Setup
130 99
131static void change_clock_rate( struct Ay_Emu *this, long rate ) 100static void change_clock_rate( struct Ay_Emu *this, int rate )
132{ 101{
133 this->clock_rate_ = rate; 102 this->clock_rate_ = rate;
134 Buffer_clock_rate( &this->stereo_buf, rate ); 103 Buffer_clock_rate( &this->stereo_buf, rate );
135} 104}
136 105
137blargg_err_t Ay_load_mem( struct Ay_Emu *this, byte const in [], int size ) 106blargg_err_t Ay_load_mem( struct Ay_Emu *this, byte const in [], long size )
138{ 107{
108 // Unload
109 this->voice_count = 0;
110 this->track_count = 0;
111 this->m3u.size = 0;
112 clear_track_vars( this );
113
139 assert( offsetof (struct header_t,track_info [2]) == header_size ); 114 assert( offsetof (struct header_t,track_info [2]) == header_size );
140 115
141 RETURN_ERR( parse_header( in, size, &this->file ) ); 116 RETURN_ERR( parse_header( in, size, &this->file ) );
@@ -144,19 +119,22 @@ blargg_err_t Ay_load_mem( struct Ay_Emu *this, byte const in [], int size )
144 warning( "Unknown file version" ); */ 119 warning( "Unknown file version" ); */
145 120
146 this->voice_count = ay_osc_count + 1; // +1 for beeper 121 this->voice_count = ay_osc_count + 1; // +1 for beeper
122 static int const types [ay_osc_count + 1] = {
123 wave_type+0, wave_type+1, wave_type+2, mixed_type+1
124 };
125 this->voice_types = types;
126
147 Ay_apu_volume( &this->apu, this->gain); 127 Ay_apu_volume( &this->apu, this->gain);
148 128
149 // Setup buffer 129 // Setup buffer
150 change_clock_rate( this, spectrum_clock ); 130 change_clock_rate( this, spectrum_clock );
131 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
151 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); 132 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
152 133
153 Sound_set_tempo( this, this->tempo ); 134 Sound_set_tempo( this, this->tempo );
154
155 // Remute voices
156 Sound_mute_voices( this, this->mute_mask_ ); 135 Sound_mute_voices( this, this->mute_mask_ );
157 136
158 this->track_count = this->file.header->max_track + 1; 137 this->track_count = this->file.header->max_track + 1;
159 this->m3u.size = 0;
160 return 0; 138 return 0;
161} 139}
162 140
@@ -298,7 +276,7 @@ enable_cpc:
298 } 276 }
299} 277}
300 278
301blargg_err_t Ay_set_sample_rate( struct Ay_Emu *this, long rate ) 279blargg_err_t Ay_set_sample_rate( struct Ay_Emu *this, int rate )
302{ 280{
303 require( !this->sample_rate ); // sample rate can't be changed once set 281 require( !this->sample_rate ); // sample rate can't be changed once set
304 Buffer_init( &this->stereo_buf ); 282 Buffer_init( &this->stereo_buf );
@@ -308,6 +286,8 @@ blargg_err_t Ay_set_sample_rate( struct Ay_Emu *this, long rate )
308 Buffer_bass_freq( &this->stereo_buf, 160 ); 286 Buffer_bass_freq( &this->stereo_buf, 160 );
309 287
310 this->sample_rate = rate; 288 this->sample_rate = rate;
289 RETURN_ERR( track_init( &this->track_filter, this ) );
290 this->tfilter.max_silence = 6 * stereo * this->sample_rate;
311 return 0; 291 return 0;
312} 292}
313 293
@@ -335,7 +315,7 @@ void Sound_mute_voices( struct Ay_Emu *this, int mask )
335 } 315 }
336 else 316 else
337 { 317 {
338 struct channel_t ch = Buffer_channel( &this->stereo_buf ); 318 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
339 assert( (ch.center && ch.left && ch.right) || 319 assert( (ch.center && ch.left && ch.right) ||
340 (!ch.center && !ch.left && !ch.right) ); // all or nothing 320 (!ch.center && !ch.left && !ch.right) ); // all or nothing
341 set_voice( this, i, ch.center ); 321 set_voice( this, i, ch.center );
@@ -359,7 +339,6 @@ void Sound_set_tempo( struct Ay_Emu *this, int t )
359 this->play_period = (blip_time_t) ((p * FP_ONE_TEMPO) / t); 339 this->play_period = (blip_time_t) ((p * FP_ONE_TEMPO) / t);
360} 340}
361 341
362void fill_buf( struct Ay_Emu *this );;
363blargg_err_t Ay_start_track( struct Ay_Emu *this, int track ) 342blargg_err_t Ay_start_track( struct Ay_Emu *this, int track )
364{ 343{
365 clear_track_vars( this ); 344 clear_track_vars( this );
@@ -496,272 +475,109 @@ blargg_err_t Ay_start_track( struct Ay_Emu *this, int track )
496 Ay_apu_write_addr( &this->apu, 7 ); 475 Ay_apu_write_addr( &this->apu, 7 );
497 Ay_apu_write_data( &this->apu, 0, 0x38 ); 476 Ay_apu_write_data( &this->apu, 0, 0x38 );
498 477
499 this->emu_track_ended_ = false; 478 // convert filter times to samples
500 this->track_ended = false; 479 struct setup_t s = this->tfilter;
480 s.max_initial *= this->sample_rate * stereo;
481 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
482 s.lookahead = 1;
483 #endif
484 track_setup( &this->track_filter, &s );
501 485
502 if ( !this->ignore_silence ) 486 return track_start( &this->track_filter );
503 {
504 // play until non-silence or end of track
505 long end;
506 for ( end = this->max_initial_silence * stereo * this->sample_rate; this->emu_time < end; )
507 {
508 fill_buf( this );
509 if ( this->buf_remain | (int) this->emu_track_ended_ )
510 break;
511 }
512
513 this->emu_time = this->buf_remain;
514 this->out_time = 0;
515 this->silence_time = 0;
516 this->silence_count = 0;
517 }
518 /* return track_ended() ? warning() : 0; */
519 return 0;
520} 487}
521 488
522// Tell/Seek 489// Tell/Seek
523 490
524static blargg_long msec_to_samples( blargg_long msec, long sample_rate ) 491static int msec_to_samples( int msec, int sample_rate )
525{ 492{
526 blargg_long sec = msec / 1000; 493 int sec = msec / 1000;
527 msec -= sec * 1000; 494 msec -= sec * 1000;
528 return (sec * sample_rate + msec * sample_rate / 1000) * stereo; 495 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
529} 496}
530 497
531long Track_tell( struct Ay_Emu *this ) 498int Track_tell( struct Ay_Emu *this )
532{ 499{
533 blargg_long rate = this->sample_rate * stereo; 500 int rate = this->sample_rate * stereo;
534 blargg_long sec = this->out_time / rate; 501 int sec = track_sample_count( &this->track_filter ) / rate;
535 return sec * 1000 + (this->out_time - sec * rate) * 1000 / rate; 502 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
536} 503}
537 504
538blargg_err_t Track_seek( struct Ay_Emu *this, long msec ) 505blargg_err_t Track_seek( struct Ay_Emu *this, int msec )
539{ 506{
540 blargg_long time = msec_to_samples( msec, this->sample_rate ); 507 int time = msec_to_samples( msec, this->sample_rate );
541 if ( time < this->out_time ) 508 if ( time < track_sample_count( &this->track_filter ) )
542 RETURN_ERR( Ay_start_track( this, this->current_track ) ); 509 RETURN_ERR( Ay_start_track( this, this->current_track ) );
543 return Track_skip( this, time - this->out_time ); 510 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
544} 511}
545 512
546blargg_err_t play_( struct Ay_Emu *this, long count, sample_t* out ); 513blargg_err_t skip_( void *emu, int count )
547static blargg_err_t skip_( struct Ay_Emu *this, long count )
548{ 514{
515 struct Ay_Emu* this = (struct Ay_Emu*) emu;
516
549 // for long skip, mute sound 517 // for long skip, mute sound
550 const long threshold = 30000; 518 const int threshold = 32768;
551 if ( count > threshold ) 519 if ( count > threshold )
552 { 520 {
553 int saved_mute = this->mute_mask_; 521 int saved_mute = this->mute_mask_;
554 Sound_mute_voices( this, ~0 ); 522 Sound_mute_voices( this, ~0 );
555
556 while ( count > threshold / 2 && !this->emu_track_ended_ )
557 {
558 RETURN_ERR( play_( this, buf_size, this->buf ) );
559 count -= buf_size;
560 }
561
562 Sound_mute_voices( this, saved_mute );
563 }
564
565 while ( count && !this->emu_track_ended_ )
566 {
567 long n = buf_size;
568 if ( n > count )
569 n = count;
570 count -= n;
571 RETURN_ERR( play_( this, n, this->buf ) );
572 }
573 return 0;
574}
575 523
576blargg_err_t Track_skip( struct Ay_Emu *this, long count ) 524 int n = count - threshold/2;
577{ 525 n &= ~(2048-1); // round to multiple of 2048
578 require( this->current_track >= 0 ); // start_track() must have been called already
579 this->out_time += count;
580
581 // remove from silence and buf first
582 {
583 long n = min( count, this->silence_count );
584 this->silence_count -= n;
585 count -= n; 526 count -= n;
586 527 RETURN_ERR( skippy_( &this->track_filter, n ) );
587 n = min( count, this->buf_remain );
588 this->buf_remain -= n;
589 count -= n;
590 }
591
592 if ( count && !this->emu_track_ended_ )
593 {
594 this->emu_time += count;
595
596 // End track if error
597 if ( skip_( this, count ) )
598 this->emu_track_ended_ = true;
599 }
600
601 if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended
602 this->track_ended |= this->emu_track_ended_;
603
604 return 0;
605}
606 528
607// Fading 529 Sound_mute_voices( this, saved_mute );
530 }
608 531
609void Track_set_fade( struct Ay_Emu *this, long start_msec, long length_msec ) 532 return skippy_( &this->track_filter, count );
610{
611 this->fade_step = this->sample_rate * length_msec / (fade_block_size * fade_shift * 1000 / stereo);
612 this->fade_start = msec_to_samples( start_msec, this->sample_rate );
613} 533}
614 534
615// unit / pow( 2.0, (double) x / step ) 535blargg_err_t Track_skip( struct Ay_Emu *this, int count )
616static int int_log( blargg_long x, int step, int unit )
617{ 536{
618 int shift = x / step; 537 require( this->current_track >= 0 ); // start_track() must have been called already
619 int fraction = (x - shift * step) * unit / step; 538 return track_skip( &this->track_filter, count );
620 return ((unit - fraction) + (fraction >> 1)) >> shift;
621} 539}
622 540
623static void handle_fade( struct Ay_Emu *this, long out_count, sample_t* out ) 541int Track_get_length( struct Ay_Emu* this, int n )
624{ 542{
625 int i; 543 int length = 0;
626 for ( i = 0; i < out_count; i += fade_block_size )
627 {
628 int const shift = 14;
629 int const unit = 1 << shift;
630 int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size,
631 this->fade_step, unit );
632 if ( gain < (unit >> fade_shift) )
633 this->track_ended = this->emu_track_ended_ = true;
634
635 sample_t* io = &out [i];
636 int count;
637 for ( count = min( fade_block_size, out_count - i ); count; --count )
638 {
639 *io = (sample_t) ((*io * gain) >> shift);
640 ++io;
641 }
642 }
643}
644 544
645// Silence detection 545 byte const* track_info = get_data( &this->file, this->file.tracks + n * 4 + 2, 6 );
546 if ( track_info )
547 length = get_be16( track_info + 4 ) * (1000 / 50); // frames to msec
646 548
647static void emu_play( struct Ay_Emu *this, long count, sample_t* out ) 549 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
648{ 550 struct entry_t* entry = &this->m3u.entries [n];
649 check( current_track_ >= 0 ); 551 length = entry->length;
650 this->emu_time += count; 552 }
651 if ( this->current_track >= 0 && !this->emu_track_ended_ ) { 553
652 if ( play_( this, count, out ) ) 554 if ( length <= 0 )
653 this->emu_track_ended_ = true; 555 length = 120 * 1000; /* 2 minutes */
654 }
655 else
656 memset( out, 0, count * sizeof *out );
657}
658 556
659// number of consecutive silent samples at end 557 return length;
660static long count_silence( sample_t* begin, long size )
661{
662 sample_t first = *begin;
663 *begin = silence_threshold; // sentinel
664 sample_t* p = begin + size;
665 while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
666 *begin = first;
667 return size - (p - begin);
668} 558}
669 559
670// fill internal buffer and check it for silence 560void Track_set_fade( struct Ay_Emu *this, int start_msec, int length_msec )
671void fill_buf( struct Ay_Emu *this )
672{ 561{
673 assert( !this->buf_remain ); 562 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
674 if ( !this->emu_track_ended_ ) 563 length_msec * this->sample_rate / (1000 / stereo) );
675 {
676 emu_play( this, buf_size, this->buf );
677 long silence = count_silence( this->buf, buf_size );
678 if ( silence < buf_size )
679 {
680 this->silence_time = this->emu_time - silence;
681 this->buf_remain = buf_size;
682 return;
683 }
684 }
685 this->silence_count += buf_size;
686} 564}
687 565
688blargg_err_t Ay_play( struct Ay_Emu *this, long out_count, sample_t* out ) 566blargg_err_t Ay_play( struct Ay_Emu *this, int out_count, sample_t* out )
689{ 567{
690 if ( this->track_ended ) 568 require( this->current_track >= 0 );
691 { 569 require( out_count % stereo == 0 );
692 memset( out, 0, out_count * sizeof *out ); 570 return track_play( &this->track_filter, out_count, out );
693 }
694 else
695 {
696 require( this->current_track >= 0 );
697 require( out_count % stereo == 0 );
698
699 assert( this->emu_time >= this->out_time );
700
701 // prints nifty graph of how far ahead we are when searching for silence
702 //debug_printf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" );
703
704 long pos = 0;
705 if ( this->silence_count )
706 {
707 // during a run of silence, run emulator at >=2x speed so it gets ahead
708 long ahead_time = this->silence_lookahead * (this->out_time + out_count - this->silence_time) + this->silence_time;
709 while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) )
710 fill_buf( this );
711
712 // fill with silence
713 pos = min( this->silence_count, out_count );
714 memset( out, 0, pos * sizeof *out );
715 this->silence_count -= pos;
716
717 if ( this->emu_time - this->silence_time > silence_max * stereo * this->sample_rate )
718 {
719 this->track_ended = this->emu_track_ended_ = true;
720 this->silence_count = 0;
721 this->buf_remain = 0;
722 }
723 }
724
725 if ( this->buf_remain )
726 {
727 // empty silence buf
728 long n = min( this->buf_remain, out_count - pos );
729 memcpy( &out [pos], this->buf + (buf_size - this->buf_remain), n * sizeof *out );
730 this->buf_remain -= n;
731 pos += n;
732 }
733
734 // generate remaining samples normally
735 long remain = out_count - pos;
736 if ( remain )
737 {
738 emu_play( this, remain, out + pos );
739 this->track_ended |= this->emu_track_ended_;
740
741 if ( !this->ignore_silence || this->out_time > this->fade_start )
742 {
743 // check end for a new run of silence
744 long silence = count_silence( out + pos, remain );
745 if ( silence < remain )
746 this->silence_time = this->emu_time - silence;
747
748 if ( this->emu_time - this->silence_time >= buf_size )
749 fill_buf( this ); // cause silence detection on next play()
750 }
751 }
752
753 if ( this->out_time > this->fade_start )
754 handle_fade( this, out_count, out );
755 }
756 this->out_time += out_count;
757 return 0;
758} 571}
759 572
760blargg_err_t play_( struct Ay_Emu *this, long count, sample_t* out ) 573blargg_err_t play_( void *emu, int count, sample_t* out )
761{ 574{
762 long remain = count; 575 struct Ay_Emu* this = (struct Ay_Emu*) emu;
576
577 int remain = count;
763 while ( remain ) 578 while ( remain )
764 { 579 {
580 Buffer_disable_immediate_removal( &this->stereo_buf );
765 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain ); 581 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
766 if ( remain ) 582 if ( remain )
767 { 583 {
@@ -773,7 +589,7 @@ blargg_err_t play_( struct Ay_Emu *this, long count, sample_t* out )
773 Sound_mute_voices( this, this->mute_mask_ ); 589 Sound_mute_voices( this, this->mute_mask_ );
774 } 590 }
775 int msec = Buffer_length( &this->stereo_buf ); 591 int msec = Buffer_length( &this->stereo_buf );
776 blip_time_t clocks_emulated = (blargg_long) msec * this->clock_rate_ / 1000 - 100; 592 blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
777 RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) ); 593 RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) );
778 assert( clocks_emulated ); 594 assert( clocks_emulated );
779 Buffer_end_frame( &this->stereo_buf, clocks_emulated ); 595 Buffer_end_frame( &this->stereo_buf, clocks_emulated );
diff --git a/apps/codecs/libgme/ay_emu.h b/apps/codecs/libgme/ay_emu.h
index b320e69653..7334167876 100644
--- a/apps/codecs/libgme/ay_emu.h
+++ b/apps/codecs/libgme/ay_emu.h
@@ -10,14 +10,12 @@
10#include "z80_cpu.h" 10#include "z80_cpu.h"
11#include "ay_apu.h" 11#include "ay_apu.h"
12#include "m3u_playlist.h" 12#include "m3u_playlist.h"
13 13#include "track_filter.h"
14typedef short sample_t;
15 14
16// 64K memory to load code and data into before starting track. Caller 15// 64K memory to load code and data into before starting track. Caller
17// must parse the AY file. 16// must parse the AY file.
18enum { mem_size = 0x10000 }; 17enum { mem_size = 0x10000 };
19enum { ram_addr = 0x4000 }; // where official RAM starts 18enum { ram_addr = 0x4000 }; // where official RAM starts
20enum { buf_size = 2048 };
21 19
22// AY file header 20// AY file header
23enum { header_size = 0x14 }; 21enum { header_size = 0x14 };
@@ -62,43 +60,30 @@ struct Ay_Emu {
62 bool cpc_mode; 60 bool cpc_mode;
63 61
64 // general 62 // general
65 int max_initial_silence;
66 int voice_count; 63 int voice_count;
64 int const* voice_types;
67 int mute_mask_; 65 int mute_mask_;
68 int tempo; 66 int tempo;
69 int gain; 67 int gain;
70 68
71 long sample_rate; 69 int sample_rate;
72 70
73 // track-specific 71 // track-specific
74 int current_track; 72 int current_track;
75 int track_count; 73 int track_count;
76 blargg_long out_time; // number of samples played since start of track 74
77 blargg_long emu_time; // number of samples emulator has generated since start of track 75 int clock_rate_;
78 volatile bool track_ended;
79 bool emu_track_ended_; // emulator has reached end of track
80
81 // fading
82 blargg_long fade_start;
83 int fade_step;
84
85 // silence detection
86 bool ignore_silence;
87 int silence_lookahead; // speed to run emulator when looking ahead for silence
88 long silence_time; // number of samples where most recent silence began
89 long silence_count; // number of samples of silence to play before using buf
90 long buf_remain; // number of samples left in silence buffer
91
92 long clock_rate_;
93 unsigned buf_changed_count; 76 unsigned buf_changed_count;
94 77
95 // M3u Playlist 78 // M3u Playlist
96 struct M3u_Playlist m3u; 79 struct M3u_Playlist m3u;
97 80
98 // large items 81 // large items
82 struct setup_t tfilter;
83 struct Track_Filter track_filter;
84
99 struct Ay_Apu apu; 85 struct Ay_Apu apu;
100 sample_t buf [buf_size]; 86 struct Multi_Buffer stereo_buf; // NULL if using custom buffer
101 struct Stereo_Buffer stereo_buf; // NULL if using custom buffer
102 struct Z80_Cpu cpu; 87 struct Z80_Cpu cpu;
103 struct mem_t mem; 88 struct mem_t mem;
104}; 89};
@@ -106,46 +91,58 @@ struct Ay_Emu {
106// Basic functionality (see Gme_File.h for file loading/track info functions) 91// Basic functionality (see Gme_File.h for file loading/track info functions)
107void Ay_init( struct Ay_Emu* this ); 92void Ay_init( struct Ay_Emu* this );
108 93
109blargg_err_t Ay_load_mem( struct Ay_Emu* this, byte const in [], int size ); 94blargg_err_t Ay_load_mem( struct Ay_Emu* this, byte const in [], long size );
110 95
111// Set output sample rate. Must be called only once before loading file. 96// Set output sample rate. Must be called only once before loading file.
112blargg_err_t Ay_set_sample_rate( struct Ay_Emu* this, long sample_rate ); 97blargg_err_t Ay_set_sample_rate( struct Ay_Emu* this, int sample_rate );
113 98
114// Start a track, where 0 is the first track. Also clears warning string. 99// Start a track, where 0 is the first track. Also clears warning string.
115blargg_err_t Ay_start_track( struct Ay_Emu* this, int track ); 100blargg_err_t Ay_start_track( struct Ay_Emu* this, int track );
116 101
117// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation 102// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
118// errors set warning string, and major errors also end track. 103// errors set warning string, and major errors also end track.
119blargg_err_t Ay_play( struct Ay_Emu* this, long count, sample_t* buf ); 104blargg_err_t Ay_play( struct Ay_Emu* this, int count, sample_t* buf );
120 105
121 106
122// Track status/control 107// Track status/control
123 108
124// Number of milliseconds (1000 msec = 1 second) played since beginning of track 109// Number of milliseconds (1000 msec = 1 second) played since beginning of track
125long Track_tell( struct Ay_Emu* this ); 110int Track_tell( struct Ay_Emu* this );
126 111
127// Seek to new time in track. Seeking backwards or far forward can take a while. 112// Seek to new time in track. Seeking backwards or far forward can take a while.
128blargg_err_t Track_seek( struct Ay_Emu* this, long msec ); 113blargg_err_t Track_seek( struct Ay_Emu* this, int msec );
129 114
130// Skip n samples 115// Skip n samples
131blargg_err_t Track_skip( struct Ay_Emu* this, long n ); 116blargg_err_t Track_skip( struct Ay_Emu* this, int n );
132 117
133// Set start time and length of track fade out. Once fade ends track_ended() returns 118// Set start time and length of track fade out. Once fade ends track_ended() returns
134// true. Fade time can be changed while track is playing. 119// true. Fade time can be changed while track is playing.
135void Track_set_fade( struct Ay_Emu* this, long start_msec, long length_msec ); 120void Track_set_fade( struct Ay_Emu* this, int start_msec, int length_msec );
121
122// True if a track has reached its end
123static inline bool Track_ended( struct Ay_Emu* this )
124{
125 return track_ended( &this->track_filter );
126}
127
128// Disables automatic end-of-track detection and skipping of silence at beginning
129static inline void Track_ignore_silence( struct Ay_Emu* this, bool disable )
130{
131 this->track_filter.silence_ignored_ = disable;
132}
136 133
137// Get track length in milliseconds 134// Get track length in milliseconds
138long Track_get_length( struct Ay_Emu* this, int n ); 135int Track_get_length( struct Ay_Emu* this, int n );
139 136
140// Sound customization 137// Sound customization
141 138
142// Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed. 139// Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
143// Track length as returned by track_info() assumes a tempo of 1.0. 140// Track length as returned by track_info() assumes a tempo of 1.0.
144void Sound_set_tempo( struct Ay_Emu* this, int t ); 141void Sound_set_tempo( struct Ay_Emu* this, int t );
145 142
146// Mute/unmute voice i, where voice 0 is first voice 143// Mute/unmute voice i, where voice 0 is first voice
147void Sound_mute_voice( struct Ay_Emu* this, int index, bool mute ); 144void Sound_mute_voice( struct Ay_Emu* this, int index, bool mute );
148 145
149// Set muting state of all voices at once using a bit mask, where -1 mutes them all, 146// Set muting state of all voices at once using a bit mask, where -1 mutes them all,
150// 0 unmutes them all, 0x01 mutes just the first voice, etc. 147// 0 unmutes them all, 0x01 mutes just the first voice, etc.
151void Sound_mute_voices( struct Ay_Emu* this, int mask ); 148void Sound_mute_voices( struct Ay_Emu* this, int mask );
@@ -168,5 +165,5 @@ static inline void disable_beeper( struct Ay_Emu *this )
168 this->beeper_mask = 0; 165 this->beeper_mask = 0;
169 this->last_beeper = 0; 166 this->last_beeper = 0;
170} 167}
171 168
172#endif 169#endif
diff --git a/apps/codecs/libgme/blargg_common.h b/apps/codecs/libgme/blargg_common.h
index 65ae76ae99..a023d6b842 100644
--- a/apps/codecs/libgme/blargg_common.h
+++ b/apps/codecs/libgme/blargg_common.h
@@ -7,12 +7,12 @@
7#include <stddef.h> 7#include <stddef.h>
8#include <stdlib.h> 8#include <stdlib.h>
9#include <string.h> 9#include <string.h>
10#include <assert.h>
11#include <limits.h> 10#include <limits.h>
12 11
13#undef BLARGG_COMMON_H 12#undef BLARGG_COMMON_H
14// allow blargg_config.h to #include blargg_common.h 13// allow blargg_config.h to #include blargg_common.h
15#include "blargg_config.h" 14#include "blargg_config.h"
15#include "blargg_source.h"
16#ifndef BLARGG_COMMON_H 16#ifndef BLARGG_COMMON_H
17#define BLARGG_COMMON_H 17#define BLARGG_COMMON_H
18 18
@@ -98,19 +98,13 @@
98 static bool false = 0; 98 static bool false = 0;
99#endif 99#endif
100 100
101// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough 101/* My code depends on int being at least 32 bits. Almost everything these days
102#include <limits.h> 102uses at least 32-bit ints, so it's hard to even find a system with 16-bit ints
103 103to test with. The issue can't be gotten around by using a suitable blargg_int
104#if INT_MAX >= 0x7FFFFFFF 104everywhere either, because int is often converted to implicitly when doing
105 typedef int blargg_long; 105arithmetic on smaller types. */
106#else 106#if UINT_MAX < 0xFFFFFFFF
107 typedef long blargg_long; 107 #error "int must be at least 32 bits"
108#endif
109
110#if UINT_MAX >= 0xFFFFFFFF
111 typedef unsigned blargg_ulong;
112#else
113 typedef unsigned long blargg_ulong;
114#endif 108#endif
115 109
116// int8_t etc. 110// int8_t etc.
diff --git a/apps/codecs/libgme/blargg_endian.h b/apps/codecs/libgme/blargg_endian.h
index ae55d7fd3b..dce5cb2048 100644
--- a/apps/codecs/libgme/blargg_endian.h
+++ b/apps/codecs/libgme/blargg_endian.h
@@ -64,45 +64,60 @@ static inline void blargg_verify_byte_order( void )
64 #endif 64 #endif
65} 65}
66 66
67static inline unsigned get_le16( void const* p ) { 67static inline unsigned get_le16( void const* p )
68 return ((unsigned char const*) p) [1] * 0x100u + 68{
69 ((unsigned char const*) p) [0]; 69 return (unsigned) ((unsigned char const*) p) [1] << 8 |
70 (unsigned) ((unsigned char const*) p) [0];
70} 71}
71static inline unsigned get_be16( void const* p ) { 72
72 return ((unsigned char const*) p) [0] * 0x100u + 73static inline unsigned get_be16( void const* p )
73 ((unsigned char const*) p) [1]; 74{
75 return (unsigned) ((unsigned char const*) p) [0] << 8 |
76 (unsigned) ((unsigned char const*) p) [1];
74} 77}
75static inline blargg_ulong get_le32( void const* p ) { 78
76 return ((unsigned char const*) p) [3] * 0x01000000u + 79static inline unsigned get_le32( void const* p )
77 ((unsigned char const*) p) [2] * 0x00010000u + 80{
78 ((unsigned char const*) p) [1] * 0x00000100u + 81 return (unsigned) ((unsigned char const*) p) [3] << 24 |
79 ((unsigned char const*) p) [0]; 82 (unsigned) ((unsigned char const*) p) [2] << 16 |
83 (unsigned) ((unsigned char const*) p) [1] << 8 |
84 (unsigned) ((unsigned char const*) p) [0];
80} 85}
81static inline blargg_ulong get_be32( void const* p ) { 86
82 return ((unsigned char const*) p) [0] * 0x01000000u + 87static inline unsigned get_be32( void const* p )
83 ((unsigned char const*) p) [1] * 0x00010000u + 88{
84 ((unsigned char const*) p) [2] * 0x00000100u + 89 return (unsigned) ((unsigned char const*) p) [0] << 24 |
85 ((unsigned char const*) p) [3]; 90 (unsigned) ((unsigned char const*) p) [1] << 16 |
91 (unsigned) ((unsigned char const*) p) [2] << 8 |
92 (unsigned) ((unsigned char const*) p) [3];
86} 93}
87static inline void set_le16( void* p, unsigned n ) { 94
95static inline void set_le16( void* p, unsigned n )
96{
88 ((unsigned char*) p) [1] = (unsigned char) (n >> 8); 97 ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
89 ((unsigned char*) p) [0] = (unsigned char) n; 98 ((unsigned char*) p) [0] = (unsigned char) n;
90} 99}
91static inline void set_be16( void* p, unsigned n ) { 100
101static inline void set_be16( void* p, unsigned n )
102{
92 ((unsigned char*) p) [0] = (unsigned char) (n >> 8); 103 ((unsigned char*) p) [0] = (unsigned char) (n >> 8);
93 ((unsigned char*) p) [1] = (unsigned char) n; 104 ((unsigned char*) p) [1] = (unsigned char) n;
94} 105}
95static inline void set_le32( void* p, blargg_ulong n ) { 106
96 ((unsigned char*) p) [3] = (unsigned char) (n >> 24); 107static inline void set_le32( void* p, unsigned n )
97 ((unsigned char*) p) [2] = (unsigned char) (n >> 16); 108{
98 ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
99 ((unsigned char*) p) [0] = (unsigned char) n; 109 ((unsigned char*) p) [0] = (unsigned char) n;
110 ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
111 ((unsigned char*) p) [2] = (unsigned char) (n >> 16);
112 ((unsigned char*) p) [3] = (unsigned char) (n >> 24);
100} 113}
101static inline void set_be32( void* p, blargg_ulong n ) { 114
102 ((unsigned char*) p) [0] = (unsigned char) (n >> 24); 115static inline void set_be32( void* p, unsigned n )
103 ((unsigned char*) p) [1] = (unsigned char) (n >> 16); 116{
104 ((unsigned char*) p) [2] = (unsigned char) (n >> 8);
105 ((unsigned char*) p) [3] = (unsigned char) n; 117 ((unsigned char*) p) [3] = (unsigned char) n;
118 ((unsigned char*) p) [2] = (unsigned char) (n >> 8);
119 ((unsigned char*) p) [1] = (unsigned char) (n >> 16);
120 ((unsigned char*) p) [0] = (unsigned char) (n >> 24);
106} 121}
107 122
108#if defined(BLARGG_NONPORTABLE) 123#if defined(BLARGG_NONPORTABLE)
@@ -132,15 +147,21 @@ static inline void set_be32( void* p, blargg_ulong n ) {
132 147
133#ifndef GET_LE16 148#ifndef GET_LE16
134 #define GET_LE16( addr ) get_le16( addr ) 149 #define GET_LE16( addr ) get_le16( addr )
135 #define GET_LE32( addr ) get_le32( addr )
136 #define SET_LE16( addr, data ) set_le16( addr, data ) 150 #define SET_LE16( addr, data ) set_le16( addr, data )
151#endif
152
153#ifndef GET_LE32
154 #define GET_LE32( addr ) get_le32( addr )
137 #define SET_LE32( addr, data ) set_le32( addr, data ) 155 #define SET_LE32( addr, data ) set_le32( addr, data )
138#endif 156#endif
139 157
140#ifndef GET_BE16 158#ifndef GET_BE16
141 #define GET_BE16( addr ) get_be16( addr ) 159 #define GET_BE16( addr ) get_be16( addr )
142 #define GET_BE32( addr ) get_be32( addr )
143 #define SET_BE16( addr, data ) set_be16( addr, data ) 160 #define SET_BE16( addr, data ) set_be16( addr, data )
161#endif
162
163#ifndef GET_BE32
164 #define GET_BE32( addr ) get_be32( addr )
144 #define SET_BE32( addr, data ) set_be32( addr, data ) 165 #define SET_BE32( addr, data ) set_be32( addr, data )
145#endif 166#endif
146 167
diff --git a/apps/codecs/libgme/blargg_source.h b/apps/codecs/libgme/blargg_source.h
index 4bea02a48b..ab8e1b072b 100644
--- a/apps/codecs/libgme/blargg_source.h
+++ b/apps/codecs/libgme/blargg_source.h
@@ -2,16 +2,13 @@
2#ifndef BLARGG_SOURCE_H 2#ifndef BLARGG_SOURCE_H
3#define BLARGG_SOURCE_H 3#define BLARGG_SOURCE_H
4 4
5// If debugging is enabled, abort program if expr is false. Meant for checking
6// internal state and consistency. A failed assertion indicates a bug in the module.
7// void assert( bool expr );
8#include <assert.h>
9
10// If debugging is enabled and expr is false, abort program. Meant for checking 5// If debugging is enabled and expr is false, abort program. Meant for checking
11// caller-supplied parameters and operations that are outside the control of the 6// caller-supplied parameters and operations that are outside the control of the
12// module. A failed requirement indicates a bug outside the module. 7// module. A failed requirement indicates a bug outside the module.
13// void require( bool expr ); 8// void require( bool expr );
14#if defined(ROCKBOX) 9#if defined(ROCKBOX)
10#undef assert
11#define assert( expr )
15#undef require 12#undef require
16#define require( expr ) 13#define require( expr )
17#else 14#else
@@ -36,28 +33,36 @@ static inline void blargg_dprintf_( const char* fmt, ... ) { }
36#undef check 33#undef check
37#define check( expr ) ((void) 0) 34#define check( expr ) ((void) 0)
38 35
39// If expr yields error string, return it from current function, otherwise continue. 36/* If expr yields non-NULL error string, returns it from current function,
40#undef RETURN_ERR 37otherwise continues normally. */
41#define RETURN_ERR( expr ) do { \ 38#undef RETURN_ERR
42 blargg_err_t blargg_return_err_ = (expr); \ 39#define RETURN_ERR( expr ) \
43 if ( blargg_return_err_ ) return blargg_return_err_; \ 40 do {\
41 blargg_err_t blargg_return_err_ = (expr);\
42 if ( blargg_return_err_ )\
43 return blargg_return_err_;\
44 } while ( 0 ) 44 } while ( 0 )
45 45
46// If ptr is 0, return out of memory error string. 46/* If ptr is NULL, returns out-of-memory error, otherwise continues normally. */
47#undef CHECK_ALLOC 47#undef CHECK_ALLOC
48#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 ) 48#define CHECK_ALLOC( ptr ) \
49 do {\
50 if ( !(ptr) )\
51 return "Out of memory";\
52 } while ( 0 )
49 53
50#ifndef max 54#ifndef max
51 #define max(a,b) (((a) > (b)) ? (a) : (b)) 55 #define max(a,b) (((a) > (b)) ? (a) : (b))
52#endif 56#endif
57
53#ifndef min 58#ifndef min
54 #define min(a,b) (((a) < (b)) ? (a) : (b)) 59 #define min(a,b) (((a) < (b)) ? (a) : (b))
55#endif 60#endif
56 61
57// TODO: good idea? bad idea? 62// typedef unsigned char byte;
58#undef byte 63typedef unsigned char blargg_byte;
59#define byte byte_ 64#undef byte
60typedef unsigned char byte; 65#define byte blargg_byte
61 66
62// deprecated 67// deprecated
63#define BLARGG_CHECK_ALLOC CHECK_ALLOC 68#define BLARGG_CHECK_ALLOC CHECK_ALLOC
diff --git a/apps/codecs/libgme/blip_buffer.c b/apps/codecs/libgme/blip_buffer.c
index d8ecbb8bb2..ba0a6558d2 100644
--- a/apps/codecs/libgme/blip_buffer.c
+++ b/apps/codecs/libgme/blip_buffer.c
@@ -2,7 +2,6 @@
2 2
3#include "blip_buffer.h" 3#include "blip_buffer.h"
4 4
5#include <assert.h>
6#include <limits.h> 5#include <limits.h>
7#include <string.h> 6#include <string.h>
8#include <stdlib.h> 7#include <stdlib.h>
@@ -19,96 +18,78 @@ details. You should have received a copy of the GNU Lesser General Public
19License along with this module; if not, write to the Free Software Foundation, 18License along with this module; if not, write to the Free Software Foundation,
20Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 19Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
21 20
22#ifdef BLARGG_ENABLE_OPTIMIZER 21#include "blargg_source.h"
23 #include BLARGG_ENABLE_OPTIMIZER
24#endif
25
26int const silent_buf_size = 1; // size used for Silent_Blip_Buffer
27 22
28void Blip_init( struct Blip_Buffer* this ) 23void Blip_init( struct Blip_Buffer* this )
29{ 24{
30 this->factor_ = (blip_ulong)LONG_MAX; 25 this->factor_ = UINT_MAX/2 + 1;;
31 this->offset_ = 0; 26 this->buffer_center_ = NULL;
32 this->buffer_size_ = 0; 27 this->buffer_size_ = 0;
33 this->sample_rate_ = 0; 28 this->sample_rate_ = 0;
34 this->reader_accum_ = 0; 29 this->bass_shift_ = 0;
35 this->bass_shift_ = 0; 30 this->clock_rate_ = 0;
36 this->clock_rate_ = 0; 31 this->bass_freq_ = 16;
37 this->bass_freq_ = 16; 32 this->length_ = 0;
38 this->length_ = 0; 33
39
40 // assumptions code makes about implementation-defined features 34 // assumptions code makes about implementation-defined features
41 #ifndef NDEBUG 35 #ifndef NDEBUG
42 // right shift of negative value preserves sign 36 // right shift of negative value preserves sign
43 buf_t_ i = -0x7FFFFFFE; 37 buf_t_ i = -0x7FFFFFFE;
44 assert( (i >> 1) == -0x3FFFFFFF ); 38 assert( (i >> 1) == -0x3FFFFFFF );
45 39
46 // casting to short truncates to 16 bits and sign-extends 40 // casting to short truncates to 16 bits and sign-extends
47 i = 0x18000; 41 i = 0x18000;
48 assert( (short) i == -0x8000 ); 42 assert( (short) i == -0x8000 );
49 #endif 43 #endif
50}
51 44
52void Blip_stop( struct Blip_Buffer* this ) 45 Blip_clear( this );
53{
54 if ( this->buffer_size_ != silent_buf_size )
55 free( this->buffer_ );
56} 46}
57 47
58void Blip_clear( struct Blip_Buffer* this, int entire_buffer ) 48void Blip_clear( struct Blip_Buffer* this )
59{ 49{
60 this->offset_ = 0; 50 bool const entire_buffer = true;
51
52 this->offset_ = 0;
61 this->reader_accum_ = 0; 53 this->reader_accum_ = 0;
62 this->modified_ = 0; 54 this->modified = false;
55
63 if ( this->buffer_ ) 56 if ( this->buffer_ )
64 { 57 {
65 long count = (entire_buffer ? this->buffer_size_ : Blip_samples_avail( this )); 58 int count = (entire_buffer ? this->buffer_size_ : Blip_samples_avail( this ));
66 memset( this->buffer_, 0, (count + blip_buffer_extra_) * sizeof (buf_t_) ); 59 memset( this->buffer_, 0, (count + blip_buffer_extra_) * sizeof (delta_t) );
67 } 60 }
68} 61}
69 62
70blargg_err_t Blip_set_sample_rate( struct Blip_Buffer* this, long new_rate, int msec ) 63blargg_err_t Blip_set_sample_rate( struct Blip_Buffer* this, int new_rate, int msec )
71{ 64{
72 if ( this->buffer_size_ == silent_buf_size ) 65 // Limit to maximum size that resampled time can represent
73 { 66 int max_size = (((blip_resampled_time_t) -1) >> BLIP_BUFFER_ACCURACY) -
74 assert( 0 ); 67 blip_buffer_extra_ - 64; // TODO: -64 isn't needed
75 return "Internal (tried to resize Silent_Blip_Buffer)"; 68 int new_size = (new_rate * (msec + 1) + 999) / 1000;
76 } 69 if ( new_size > max_size )
77 70 new_size = max_size;
78 // start with maximum length that resampled time can represent 71
79 long new_size = (ULONG_MAX >> BLIP_BUFFER_ACCURACY) - blip_buffer_extra_ - 64; 72 // Resize buffer
80 if ( msec != blip_max_length ) 73 if ( this->buffer_size_ != new_size ) {
81 { 74 this->buffer_center_ = this->buffer_ + BLIP_MAX_QUALITY/2;
82 long s = (new_rate * (msec + 1) + 999) / 1000; 75 this->buffer_size_ = new_size;
83 if ( s < new_size ) 76 }
84 new_size = s; 77
85 else
86 assert( 0 ); // fails if requested buffer length exceeds limit
87 }
88
89 if ( new_size > blip_buffer_max )
90 return "Out of memory";
91
92 this->buffer_size_ = new_size;
93 assert( this->buffer_size_ != silent_buf_size );
94
95 // update things based on the sample rate 78 // update things based on the sample rate
96 this->sample_rate_ = new_rate; 79 this->sample_rate_ = new_rate;
97 this->length_ = new_size * 1000 / new_rate - 1; 80 this->length_ = new_size * 1000 / new_rate - 1;
98 if ( msec )
99 assert( this->length_ == msec ); // ensure length is same as that passed in
100 if ( this->clock_rate_ ) 81 if ( this->clock_rate_ )
101 Blip_set_clock_rate( this, this->clock_rate_ ); 82 Blip_set_clock_rate( this, this->clock_rate_ );
102 Blip_bass_freq( this, this->bass_freq_ ); 83 Blip_bass_freq( this, this->bass_freq_ );
103 84
104 Blip_clear( this, 1 ); 85 Blip_clear( this );
105 86
106 return 0; // success 87 return 0; // success
107} 88}
108 89
109blip_resampled_time_t Blip_clock_rate_factor( struct Blip_Buffer* this, long rate ) 90blip_resampled_time_t Blip_clock_rate_factor( struct Blip_Buffer* this, int rate )
110{ 91{
111 blip_long factor = (blip_long) ( this->sample_rate_ * (1LL << BLIP_BUFFER_ACCURACY) / rate); 92 int factor = (int) ( this->sample_rate_ * (1LL << BLIP_BUFFER_ACCURACY) / rate);
112 assert( factor > 0 || !this->sample_rate_ ); // fails if clock/output ratio is too large 93 assert( factor > 0 || !this->sample_rate_ ); // fails if clock/output ratio is too large
113 return (blip_resampled_time_t) factor; 94 return (blip_resampled_time_t) factor;
114} 95}
@@ -117,119 +98,111 @@ void Blip_bass_freq( struct Blip_Buffer* this, int freq )
117{ 98{
118 this->bass_freq_ = freq; 99 this->bass_freq_ = freq;
119 int shift = 31; 100 int shift = 31;
120 if ( freq > 0 ) 101 if ( freq > 0 && this->sample_rate_ )
121 { 102 {
122 shift = 13; 103 shift = 13;
123 long f = (freq << 16) / this->sample_rate_; 104 int f = (freq << 16) / this->sample_rate_;
124 while ( (f >>= 1) && --shift ) { } 105 while ( (f >>= 1) && --shift ) { }
125 } 106 }
126 this->bass_shift_ = shift; 107 this->bass_shift_ = shift;
127} 108}
128 109
129void Blip_end_frame( struct Blip_Buffer* this, blip_time_t t ) 110void Blip_end_frame( struct Blip_Buffer* this, blip_time_t t )
130{ 111{
131 this->offset_ += t * this->factor_; 112 this->offset_ += t * this->factor_;
132 assert( Blip_samples_avail( this ) <= (long) this->buffer_size_ ); // time outside buffer length 113 assert( Blip_samples_avail( this ) <= (int) this->buffer_size_ ); // time outside buffer length
133} 114}
134 115
135void Blip_remove_silence( struct Blip_Buffer* this, long count ) 116int Blip_count_samples( struct Blip_Buffer* this, blip_time_t t )
136{ 117{
137 assert( count <= Blip_samples_avail( this ) ); // tried to remove more samples than available 118 blip_resampled_time_t last_sample = Blip_resampled_time( this, t ) >> BLIP_BUFFER_ACCURACY;
138 this->offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY; 119 blip_resampled_time_t first_sample = this->offset_ >> BLIP_BUFFER_ACCURACY;
120 return (int) (last_sample - first_sample);
139} 121}
140 122
141long Blip_count_samples( struct Blip_Buffer* this, blip_time_t t ) 123blip_time_t Blip_count_clocks( struct Blip_Buffer* this, int count )
142{ 124{
143 unsigned long last_sample = Blip_resampled_time( this, t ) >> BLIP_BUFFER_ACCURACY;
144 unsigned long first_sample = this->offset_ >> BLIP_BUFFER_ACCURACY;
145 return (long) (last_sample - first_sample);
146}
147
148blip_time_t Blip_count_clocks( struct Blip_Buffer* this, long count )
149{
150 if ( !this->factor_ )
151 {
152 assert( 0 ); // sample rate and clock rates must be set first
153 return 0;
154 }
155
156 if ( count > this->buffer_size_ ) 125 if ( count > this->buffer_size_ )
157 count = this->buffer_size_; 126 count = this->buffer_size_;
158 blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY; 127 blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
159 return (blip_time_t) ((time - this->offset_ + this->factor_ - 1) / this->factor_); 128 return (blip_time_t) ((time - this->offset_ + this->factor_ - 1) / this->factor_);
160} 129}
161 130
162void Blip_remove_samples( struct Blip_Buffer* this, long count ) 131void Blip_remove_samples( struct Blip_Buffer* this, int count )
163{ 132{
164 if ( count ) 133 if ( count )
165 { 134 {
166 Blip_remove_silence( this, count ); 135 Blip_remove_silence( this, count );
167 136
168 // copy remaining samples to beginning and clear old samples 137 // copy remaining samples to beginning and clear old samples
169 long remain = Blip_samples_avail( this ) + blip_buffer_extra_; 138 int remain = Blip_samples_avail( this ) + blip_buffer_extra_;
170 memmove( this->buffer_, this->buffer_ + count, remain * sizeof *this->buffer_ ); 139 memmove( this->buffer_, this->buffer_ + count, remain * sizeof *this->buffer_ );
171 memset( this->buffer_ + remain, 0, count * sizeof *this->buffer_ ); 140 memset( this->buffer_ + remain, 0, count * sizeof *this->buffer_ );
172 } 141 }
173} 142}
174 143
175long Blip_read_samples( struct Blip_Buffer* this, blip_sample_t* BLIP_RESTRICT out, long max_samples, int stereo ) 144int Blip_read_samples( struct Blip_Buffer* this, blip_sample_t out_ [], int max_samples, bool stereo )
176{ 145{
177 long count = Blip_samples_avail( this ); 146 int count = Blip_samples_avail( this );
178 if ( count > max_samples ) 147 if ( count > max_samples )
179 count = max_samples; 148 count = max_samples;
180 149
181 if ( count ) 150 if ( count )
182 { 151 {
183 int const bass = BLIP_READER_BASS( *this ); 152 int const bass = this->bass_shift_;
184 BLIP_READER_BEGIN( reader, *this ); 153 delta_t const* reader = this->buffer_ + count;
185 154 int reader_sum = this->reader_accum_;
155
156 blip_sample_t* BLARGG_RESTRICT out = out_ + count;
157 if ( stereo )
158 out += count;
159 int offset = -count;
160
186 if ( !stereo ) 161 if ( !stereo )
187 { 162 {
188 blip_long n; 163 do
189 for ( n = count; n; --n )
190 { 164 {
191 blip_long s = BLIP_READER_READ( reader ); 165 int s = reader_sum >> delta_bits;
192 if ( (blip_sample_t) s != s ) 166
193 s = 0x7FFF - (s >> 24); 167 reader_sum -= reader_sum >> bass;
194 *out++ = (blip_sample_t) s; 168 reader_sum += reader [offset];
195 BLIP_READER_NEXT( reader, bass ); 169
170 BLIP_CLAMP( s, s );
171 out [offset] = (blip_sample_t) s;
196 } 172 }
173 while ( ++offset );
197 } 174 }
198 else 175 else
199 { 176 {
200 blip_long n; 177 do
201 for ( n = count; n; --n )
202 { 178 {
203 blip_long s = BLIP_READER_READ( reader ); 179 int s = reader_sum >> delta_bits;
204 if ( (blip_sample_t) s != s ) 180
205 s = 0x7FFF - (s >> 24); 181 reader_sum -= reader_sum >> bass;
206 *out = (blip_sample_t) s; 182 reader_sum += reader [offset];
207 out += 2; 183
208 BLIP_READER_NEXT( reader, bass ); 184 BLIP_CLAMP( s, s );
185 out [offset * 2] = (blip_sample_t) s;
209 } 186 }
187 while ( ++offset );
210 } 188 }
211 BLIP_READER_END( reader, *this ); 189
212 190 this->reader_accum_ = reader_sum;
191
213 Blip_remove_samples( this, count ); 192 Blip_remove_samples( this, count );
214 } 193 }
215 return count; 194 return count;
216} 195}
217 196
218void Blip_mix_samples( struct Blip_Buffer* this, blip_sample_t const* in, long count ) 197void Blip_mix_samples( struct Blip_Buffer* this, blip_sample_t const in [], int count )
219{ 198{
220 if ( this->buffer_size_ == silent_buf_size ) 199 delta_t* out = this->buffer_center_ + (this->offset_ >> BLIP_BUFFER_ACCURACY);
221 { 200
222 assert( 0 );
223 return;
224 }
225
226 buf_t_* out = this->buffer_ + (this->offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2;
227
228 int const sample_shift = blip_sample_bits - 16; 201 int const sample_shift = blip_sample_bits - 16;
229 int prev = 0; 202 int prev = 0;
230 while ( count-- ) 203 while ( --count >= 0 )
231 { 204 {
232 blip_long s = (blip_long) *in++ << sample_shift; 205 int s = *in++ << sample_shift;
233 *out += s - prev; 206 *out += s - prev;
234 prev = s; 207 prev = s;
235 ++out; 208 ++out;
@@ -237,40 +210,16 @@ void Blip_mix_samples( struct Blip_Buffer* this, blip_sample_t const* in, long
237 *out -= prev; 210 *out -= prev;
238} 211}
239 212
240void Blip_set_modified( struct Blip_Buffer* this ) 213// Blip_Synth
241{
242 this->modified_ = 1;
243}
244
245int Blip_clear_modified( struct Blip_Buffer* this )
246{
247 int b = this->modified_;
248 this->modified_ = 0;
249 return b;
250}
251
252blip_resampled_time_t Blip_resampled_duration( struct Blip_Buffer* this, int t )
253{
254 return t * this->factor_;
255}
256 214
257blip_resampled_time_t Blip_resampled_time( struct Blip_Buffer* this, blip_time_t t ) 215void volume_unit( struct Blip_Synth* this, int new_unit )
258{ 216{
259 return t * this->factor_ + this->offset_; 217 this->delta_factor = (int) (new_unit * (1LL << blip_sample_bits) / FP_ONE_VOLUME);
260} 218}
261 219
262
263// Blip_Synth
264
265void Synth_init( struct Blip_Synth* this ) 220void Synth_init( struct Blip_Synth* this )
266{ 221{
267 this->buf = 0; 222 this->buf = 0;
268 this->last_amp = 0; 223 this->last_amp = 0;
269 this->delta_factor = 0; 224 this->delta_factor = 0;
270} 225}
271
272// Set overall volume of waveform
273void Synth_volume( struct Blip_Synth* this, int v )
274{
275 this->delta_factor = (int) (v * (1LL << blip_sample_bits) / FP_ONE_VOLUME);
276}
diff --git a/apps/codecs/libgme/blip_buffer.h b/apps/codecs/libgme/blip_buffer.h
index f9f1f6e969..d73a14b3eb 100644
--- a/apps/codecs/libgme/blip_buffer.h
+++ b/apps/codecs/libgme/blip_buffer.h
@@ -4,202 +4,238 @@
4#ifndef BLIP_BUFFER_H 4#ifndef BLIP_BUFFER_H
5#define BLIP_BUFFER_H 5#define BLIP_BUFFER_H
6 6
7#include <assert.h> 7#include "blargg_common.h"
8 8
9 // internal 9typedef unsigned blip_resampled_time_t;
10 #include "blargg_common.h" 10typedef int blip_time_t;
11 #if INT_MAX >= 0x7FFFFFFF 11typedef int clocks_t;
12 typedef int blip_long; 12
13 typedef unsigned blip_ulong; 13// Output samples are 16-bit signed, with a range of -32768 to 32767
14 #else 14typedef short blip_sample_t;
15 typedef long blip_long;
16 typedef unsigned long blip_ulong;
17 #endif
18 15
19// Time unit at source clock rate 16static int const blip_default_length = 1000 / 4; // Default Blip_Buffer length (1/4 second)
20typedef blip_long blip_time_t; 17
18#ifndef BLIP_MAX_QUALITY
19 #define BLIP_MAX_QUALITY 2
20#endif
21 21
22// Number of bits in resample ratio fraction. Higher values give a more accurate ratio
23// but reduce maximum buffer size.
24#ifndef BLIP_BUFFER_ACCURACY 22#ifndef BLIP_BUFFER_ACCURACY
25 #define BLIP_BUFFER_ACCURACY 16 23 #define BLIP_BUFFER_ACCURACY 16
26#endif 24#endif
27 25
28// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in 26// linear interpolation needs 8 bits
29// noticeable broadband noise when synthesizing high frequency square waves.
30// Affects size of Blip_Synth objects since they store the waveform directly.
31#ifndef BLIP_PHASE_BITS 27#ifndef BLIP_PHASE_BITS
32 #define BLIP_PHASE_BITS 8 28 #define BLIP_PHASE_BITS 8
33#endif 29#endif
34 30
35// Output samples are 16-bit signed, with a range of -32768 to 32767 31static int const blip_res = 1 << BLIP_PHASE_BITS;
36typedef short blip_sample_t; 32static int const blip_buffer_extra_ = BLIP_MAX_QUALITY + 2;
37enum { blip_sample_max = 32767 }; 33
38enum { blip_widest_impulse_ = 16 }; 34// Properties of fixed-point sample position
39enum { blip_buffer_extra_ = blip_widest_impulse_ + 2 }; 35typedef unsigned ufixed_t; // unsigned for more range, optimized shifts
40enum { blip_res = 1 << BLIP_PHASE_BITS }; 36enum { fixed_bits = BLIP_BUFFER_ACCURACY }; // bits in fraction
41enum { blip_max_length = 0 }; 37enum { fixed_unit = 1 << fixed_bits }; // 1.0 samples
42enum { blip_default_length = 250 }; 38
39// Deltas in buffer are fixed-point with this many fraction bits.
40// Less than 16 for extra range.
41enum { delta_bits = 14 };
42
43// Pointer to first committed delta sample
44typedef int delta_t;
43 45
44// Maximun buffer size (48Khz, 50 ms) 46// Maximun buffer size (48Khz, 50 ms)
45enum { blip_buffer_max = 2466 }; 47enum { blip_buffer_max = 2466 };
46enum { blip_sample_bits = 30 };
47
48typedef blip_time_t buf_t_;
49/* typedef const char* blargg_err_t; */
50typedef blip_ulong blip_resampled_time_t;
51 48
52struct Blip_Buffer { 49struct Blip_Buffer {
53 blip_ulong factor_; 50 unsigned factor_;
54 blip_resampled_time_t offset_; 51 ufixed_t offset_;
55 buf_t_ buffer_ [blip_buffer_max]; 52 delta_t* buffer_center_;
56 blip_long buffer_size_; 53 int buffer_size_;
57 blip_long reader_accum_; 54 int reader_accum_;
58 int bass_shift_; 55 int bass_shift_;
59 56 int bass_freq_;
60 long sample_rate_; 57 int sample_rate_;
61 long clock_rate_; 58 int clock_rate_;
62 int bass_freq_; 59 int length_;
63 int length_; 60 bool modified;
64 int modified_; 61
62 delta_t buffer_ [blip_buffer_max];
65}; 63};
66 64
67// not documented yet 65// Blip_Buffer_ implementation
68void Blip_set_modified( struct Blip_Buffer* this ); 66static inline ufixed_t to_fixed( struct Blip_Buffer *this, clocks_t t )
69int Blip_clear_modified( struct Blip_Buffer* this ); 67{
70void Blip_remove_silence( struct Blip_Buffer* this, long count ); 68 return t * this->factor_ + this->offset_;
71blip_resampled_time_t Blip_resampled_duration( struct Blip_Buffer* this, int t ); 69}
72blip_resampled_time_t Blip_resampled_time( struct Blip_Buffer* this, blip_time_t t );
73blip_resampled_time_t Blip_clock_rate_factor( struct Blip_Buffer* this, long clock_rate );
74
75// Initializes Blip_Buffer structure
76void Blip_init( struct Blip_Buffer* this );
77
78// Stops (clear) Blip_Buffer structure
79void Blip_stop( struct Blip_Buffer* this );
80 70
81// Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults 71static inline delta_t* delta_at( struct Blip_Buffer *this, ufixed_t f )
82// to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there 72{
83// isn't enough memory, returns error without affecting current buffer setup. 73 assert( (f >> fixed_bits) < (unsigned) this->buffer_size_ );
84blargg_err_t Blip_set_sample_rate( struct Blip_Buffer* this, long samples_per_sec, int msec_length ); 74 return this->buffer_center_ + (f >> fixed_bits);
75}
85 76
86// Set number of source time units per second 77// Number of samples available for reading with read_samples()
87static inline void Blip_set_clock_rate( struct Blip_Buffer* this, long cps ) 78static inline int Blip_samples_avail( struct Blip_Buffer* this )
88{ 79{
89 this->factor_ = Blip_clock_rate_factor( this, this->clock_rate_ = cps ); 80 return (int) (this->offset_ >> BLIP_BUFFER_ACCURACY);
90} 81}
91 82
92// End current time frame of specified duration and make its samples available 83static inline void Blip_remove_silence( struct Blip_Buffer* this, int count )
93// (along with any still-unread samples) for reading with read_samples(). Begins 84{
94// a new time frame at the end of the current frame. 85 assert( count <= Blip_samples_avail( this ) ); // tried to remove more samples than available
95void Blip_end_frame( struct Blip_Buffer* this, blip_time_t time ); 86 this->offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
87}
96 88
97// Read at most 'max_samples' out of buffer into 'dest', removing them from from 89// Initializes Blip_Buffer structure
98// the buffer. Returns number of samples actually read and removed. If stereo is 90void Blip_init( struct Blip_Buffer* this );
99// true, increments 'dest' one extra time after writing each sample, to allow
100// easy interleving of two channels into a stereo output buffer.
101long Blip_read_samples( struct Blip_Buffer* this, blip_sample_t* dest, long max_samples, int stereo );
102 91
103// Additional optional features 92// Sets output sample rate and resizes and clears sample buffer
93blargg_err_t Blip_set_sample_rate( struct Blip_Buffer* this, int samples_per_sec, int msec_length );
104 94
105// Current output sample rate 95// Current output sample rate
106static inline long Blip_sample_rate( struct Blip_Buffer* this ) 96static inline int Blip_sample_rate( struct Blip_Buffer* this )
107{ 97{
108 return this->sample_rate_; 98 return this->sample_rate_;
109} 99}
110 100
111// Length of buffer, in milliseconds 101// Sets number of source time units per second
112static inline int Blip_length( struct Blip_Buffer* this ) 102blip_resampled_time_t Blip_clock_rate_factor( struct Blip_Buffer* this, int clock_rate );
103static inline void Blip_set_clock_rate( struct Blip_Buffer* this, int clocks_per_sec )
113{ 104{
114 return this->length_; 105 this->factor_ = Blip_clock_rate_factor( this, this->clock_rate_ = clocks_per_sec );
115} 106}
116 107
117// Number of source time units per second 108// Number of source time units per second
118static inline long Blip_clock_rate( struct Blip_Buffer* this ) 109static inline int Blip_clock_rate( struct Blip_Buffer* this )
119{ 110{
120 return this->clock_rate_; 111 return this->clock_rate_;
121} 112}
122 113
114static inline int Blip_length( struct Blip_Buffer* this )
115{
116 return this->length_;
117}
118
119// Clears buffer and removes all samples
120void Blip_clear( struct Blip_Buffer* this );
121
122// Use Blip_Synth to add waveform to buffer
123
124// Resamples to time t, then subtracts t from current time. Appends result of resampling
125// to buffer for reading.
126void Blip_end_frame( struct Blip_Buffer* this, blip_time_t time ) ICODE_ATTR;
127
128
129// Reads at most n samples to out [0 to n-1] and returns number actually read. If stereo
130// is true, writes to out [0], out [2], out [4] etc. instead.
131int Blip_read_samples( struct Blip_Buffer* this, blip_sample_t out [], int n, bool stereo ) ICODE_ATTR;
132
133
134// More features
135
136// Sets flag that tells some Multi_Buffer types that sound was added to buffer,
137// so they know that it needs to be mixed in. Only needs to be called once
138// per time frame that sound was added. Not needed if not using Multi_Buffer.
139static inline void Blip_set_modified( struct Blip_Buffer* this ) { this->modified = true; }
123 140
124// Set frequency high-pass filter frequency, where higher values reduce bass more 141// Set frequency high-pass filter frequency, where higher values reduce bass more
125void Blip_bass_freq( struct Blip_Buffer* this, int frequency ); 142void Blip_bass_freq( struct Blip_Buffer* this, int frequency );
126 143
127// Number of samples delay from synthesis to samples read out
128static inline int Blip_output_latency( void )
129{
130 return blip_widest_impulse_ / 2;
131}
132 144
133// Remove all available samples and clear buffer to silence. If 'entire_buffer' is 145// Low-level features
134// false, just clears out any samples waiting rather than the entire buffer.
135void Blip_clear( struct Blip_Buffer* this, int entire_buffer );
136 146
137// Number of samples available for reading with read_samples() 147// Removes the first n samples
138static inline long Blip_samples_avail( struct Blip_Buffer* this ) 148void Blip_remove_samples( struct Blip_Buffer* this, int n ) ICODE_ATTR;
139{ 149
140 return (long) (this->offset_ >> BLIP_BUFFER_ACCURACY); 150// Returns number of clocks needed until n samples will be available.
141} 151// If buffer cannot even hold n samples, returns number of clocks
152// until buffer becomes full.
153blip_time_t Blip_count_clocks( struct Blip_Buffer* this, int count ) ICODE_ATTR;
154
155// Number of samples that should be mixed before calling Blip_end_frame( t )
156int Blip_count_samples( struct Blip_Buffer* this, blip_time_t t ) ICODE_ATTR;
157
158// Mixes n samples into buffer
159void Blip_mix_samples( struct Blip_Buffer* this, blip_sample_t const in [], int n ) ICODE_ATTR;
142 160
143// Remove 'count' samples from those waiting to be read
144void Blip_remove_samples( struct Blip_Buffer* this, long count );
145 161
146// Experimental features 162// Resampled time (sorry, poor documentation right now)
147 163
148// Count number of clocks needed until 'count' samples will be available. 164// Resampled time is fixed-point, in terms of output samples.
149// If buffer can't even hold 'count' samples, returns number of clocks until
150// buffer becomes full.
151blip_time_t Blip_count_clocks( struct Blip_Buffer* this, long count );
152 165
153// Number of raw samples that can be mixed within frame of specified duration. 166// Converts clock count to resampled time
154long Blip_count_samples( struct Blip_Buffer* this, blip_time_t duration ); 167static inline blip_resampled_time_t Blip_resampled_duration( struct Blip_Buffer* this, int t )
168{
169 return t * this->factor_;
170}
171
172// Converts clock time since beginning of current time frame to resampled time
173static inline blip_resampled_time_t Blip_resampled_time( struct Blip_Buffer* this, blip_time_t t )
174{
175 return t * this->factor_ + this->offset_;
176}
155 177
156// Mix 'count' samples from 'buf' into buffer.
157void Blip_mix_samples( struct Blip_Buffer* this, blip_sample_t const* buf, long count );
158 178
159// Range specifies the greatest expected change in amplitude. Calculate it 179// Range specifies the greatest expected change in amplitude. Calculate it
160// by finding the difference between the maximum and minimum expected 180// by finding the difference between the maximum and minimum expected
161// amplitudes (max - min). 181// amplitudes (max - min).
162 182
183typedef char coeff_t;
184
163struct Blip_Synth { 185struct Blip_Synth {
164 struct Blip_Buffer* buf;
165 int last_amp;
166 int delta_factor; 186 int delta_factor;
187 int last_amp;
188 struct Blip_Buffer* buf;
167}; 189};
168 190
191// Blip_Synth_
192void volume_unit( struct Blip_Synth* this, int new_unit );
193
169// Initializes Blip_Synth structure 194// Initializes Blip_Synth structure
170void Synth_init( struct Blip_Synth* this ); 195void Synth_init( struct Blip_Synth* this );
171 196
172// Set overall volume of waveform 197// Sets volume of amplitude delta unit
173void Synth_volume( struct Blip_Synth* this, int v ); 198static inline void Synth_volume( struct Blip_Synth* this, int v )
199{
200 volume_unit( this, v ); // new_unit = 1 / range * v
201}
174 202
175// Get/set Blip_Buffer used for output
176const struct Blip_Buffer* Synth_output( struct Blip_Synth* this );
177 203
178// Low-level interface 204// Low-level interface
179 205
180 #if defined (__GNUC__) || _MSC_VER >= 1100 206// (in >> sh & mask) * mul
181 #define BLIP_RESTRICT __restrict 207#define BLIP_SH_AND_MUL( in, sh, mask, mul ) \
182 #else 208((int) (in) / ((1U << (sh)) / (mul)) & (unsigned) ((mask) * (mul)))
183 #define BLIP_RESTRICT 209
184 #endif 210// (T*) ptr + (off >> sh)
211#define BLIP_PTR_OFF_SH( T, ptr, off, sh ) \
212 ((T*) (BLIP_SH_AND_MUL( off, sh, -1, sizeof (T) ) + (char*) (ptr)))
185 213
186// Works directly in terms of fractional output samples. Contact author for more info. 214// Works directly in terms of fractional output samples. Use resampled time functions in Blip_Buffer
215// to convert clock counts to resampled time.
187static inline void Synth_offset_resampled( struct Blip_Synth* this, blip_resampled_time_t time, 216static inline void Synth_offset_resampled( struct Blip_Synth* this, blip_resampled_time_t time,
188 int delta, struct Blip_Buffer* blip_buf ) 217 int delta, struct Blip_Buffer* blip_buf )
189{ 218{
190 // Fails if time is beyond end of Blip_Buffer, due to a bug in caller code or the 219 int const half_width = 1;
191 // need for a longer buffer as set by set_sample_rate(). 220
192 assert( (blip_long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ ); 221 delta_t* BLARGG_RESTRICT buf = delta_at( blip_buf, time );
193 delta *= this->delta_factor; 222 delta *= this->delta_factor;
194 blip_long* BLIP_RESTRICT buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY);
195 int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1));
196 223
197 blip_long left = buf [0] + delta; 224 int const phase_shift = BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS;
225 int const phase = (half_width & (half_width - 1)) ?
226 (int) BLIP_SH_AND_MUL( time, phase_shift, blip_res - 1, sizeof (coeff_t) ) * half_width :
227 (int) BLIP_SH_AND_MUL( time, phase_shift, blip_res - 1, sizeof (coeff_t) * half_width );
228
229 int left = buf [0] + delta;
198 230
199 // Kind of crappy, but doing shift after multiply results in overflow. 231 // Kind of crappy, but doing shift after multiply results in overflow.
200 // Alternate way of delaying multiply by delta_factor results in worse 232 // Alternate way of delaying multiply by delta_factor results in worse
201 // sub-sample resolution. 233 // sub-sample resolution.
202 blip_long right = (delta >> BLIP_PHASE_BITS) * phase; 234 int right = (delta >> BLIP_PHASE_BITS) * phase;
235 #ifdef BLIP_BUFFER_NOINTERP
236 // TODO: remove? (just a hack to see how it sounds)
237 right = 0;
238 #endif
203 left -= right; 239 left -= right;
204 right += buf [1]; 240 right += buf [1];
205 241
@@ -213,33 +249,38 @@ static inline void Synth_update( struct Blip_Synth* this, blip_time_t t, int amp
213{ 249{
214 int delta = amp - this->last_amp; 250 int delta = amp - this->last_amp;
215 this->last_amp = amp; 251 this->last_amp = amp;
216 Synth_offset_resampled( this, t * this->buf->factor_ + this->buf->offset_, delta, this->buf ); 252 Synth_offset_resampled( this, to_fixed(this->buf, t), delta, this->buf );
217} 253}
218 254
219// Add an amplitude transition of specified delta, optionally into specified buffer 255// Adds amplitude transition at time t. Delta can be positive or negative.
220// rather than the one set with output(). Delta can be positive or negative. 256// The actual change in amplitude is delta * volume.
221// The actual change in amplitude is delta * (volume / range)
222static inline void Synth_offset( struct Blip_Synth* this, blip_time_t t, int delta, struct Blip_Buffer* buf )
223{
224 Synth_offset_resampled( this, t * buf->factor_ + buf->offset_, delta, buf );
225}
226
227// Same as offset(), except code is inlined for higher performance
228static inline void Synth_offset_inline( struct Blip_Synth* this, blip_time_t t, int delta, struct Blip_Buffer* buf ) 257static inline void Synth_offset_inline( struct Blip_Synth* this, blip_time_t t, int delta, struct Blip_Buffer* buf )
229{ 258{
230 Synth_offset_resampled( this, t * buf->factor_ + buf->offset_, delta, buf ); 259 Synth_offset_resampled( this, to_fixed(buf, t), delta, buf );
231} 260}
232 261
262#define Synth_offset( synth, time, delta, buf ) Synth_offset_inline( synth, time, delta, buf )
263
264// Number of bits in raw sample that covers normal output range. Less than 32 bits to give
265// extra amplitude range. That is,
266// +1 << (blip_sample_bits-1) = +1.0
267// -1 << (blip_sample_bits-1) = -1.0
268static int const blip_sample_bits = 30;
269
233// Optimized reading from Blip_Buffer, for use in custom sample output 270// Optimized reading from Blip_Buffer, for use in custom sample output
234 271
235// Begin reading from buffer. Name should be unique to the current block. 272// Begin reading from buffer. Name should be unique to the current block.
236#define BLIP_READER_BEGIN( name, blip_buffer ) \ 273#define BLIP_READER_BEGIN( name, blip_buffer ) \
237 buf_t_* BLIP_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\ 274 const delta_t* BLARGG_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\
238 blip_long name##_reader_accum = (blip_buffer).reader_accum_ 275 int name##_reader_accum = (blip_buffer).reader_accum_
239 276
240// Get value to pass to BLIP_READER_NEXT() 277// Get value to pass to BLIP_READER_NEXT()
241#define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_) 278#define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_)
242 279
280// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal
281// code at the cost of having no bass_freq() functionality
282static int const blip_reader_default_bass = 9;
283
243// Current sample 284// Current sample
244#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16)) 285#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16))
245 286
@@ -254,7 +295,7 @@ static inline void Synth_offset_inline( struct Blip_Synth* this, blip_time_t t,
254// using Blip_remove_samples(). 295// using Blip_remove_samples().
255#define BLIP_READER_END( name, blip_buffer ) \ 296#define BLIP_READER_END( name, blip_buffer ) \
256 (void) ((blip_buffer).reader_accum_ = name##_reader_accum) 297 (void) ((blip_buffer).reader_accum_ = name##_reader_accum)
257 298
258#define BLIP_READER_ADJ_( name, offset ) (name##_reader_buf += offset) 299#define BLIP_READER_ADJ_( name, offset ) (name##_reader_buf += offset)
259 300
260#define BLIP_READER_NEXT_IDX_( name, bass, idx ) {\ 301#define BLIP_READER_NEXT_IDX_( name, bass, idx ) {\
@@ -262,18 +303,33 @@ static inline void Synth_offset_inline( struct Blip_Synth* this, blip_time_t t,
262 name##_reader_accum += name##_reader_buf [(idx)];\ 303 name##_reader_accum += name##_reader_buf [(idx)];\
263} 304}
264 305
306#define BLIP_READER_NEXT_RAW_IDX_( name, bass, idx ) {\
307 name##_reader_accum -= name##_reader_accum >> (bass);\
308 name##_reader_accum +=\
309 *(delta_t const*) ((char const*) name##_reader_buf + (idx));\
310}
311
265//// BLIP_CLAMP 312//// BLIP_CLAMP
266 313
267#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ 314#if ARM_ARCH >= 6
268 defined (__x86_64__) || defined (__ia64__) || defined (__i386__) 315 #define BLIP_CLAMP( sample, out ) \
269 #define BLIP_X86 1 316 ({ \
270 #define BLIP_CLAMP_( in ) in < -0x8000 || 0x7FFF < in 317 asm ("ssat %0, #16, %1" \
318 : "=r" ( out ) : "r"( sample ) ); \
319 out; \
320 })
271#else 321#else
272 #define BLIP_CLAMP_( in ) (blip_sample_t) in != in 322 #if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
273#endif 323 defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
324 #define BLIP_X86 1
325 #define BLIP_CLAMP_( in ) in < -0x8000 || 0x7FFF < in
326 #else
327 #define BLIP_CLAMP_( in ) (blip_sample_t) in != in
328 #endif
274 329
275// Clamp sample to blip_sample_t range 330 // Clamp sample to blip_sample_t range
276#define BLIP_CLAMP( sample, out )\ 331 #define BLIP_CLAMP( sample, out )\
277 { if ( BLIP_CLAMP_( (sample) ) ) (out) = ((sample) >> 31) ^ 0x7FFF; } 332 { if ( BLIP_CLAMP_( (sample) ) ) (out) = ((sample) >> 31) ^ 0x7FFF; }
333#endif
278 334
279#endif 335#endif
diff --git a/apps/codecs/libgme/gbs_cpu.c b/apps/codecs/libgme/gbs_cpu.c
index 998888fe72..1015dd5358 100644
--- a/apps/codecs/libgme/gbs_cpu.c
+++ b/apps/codecs/libgme/gbs_cpu.c
@@ -20,7 +20,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
20 #define LOG_MEM( addr, str, data ) data 20 #define LOG_MEM( addr, str, data ) data
21#endif 21#endif
22 22
23int Read_mem( struct Gbs_Emu* this, addr_t addr ) 23int read_mem( struct Gbs_Emu* this, addr_t addr )
24{ 24{
25 int result = *Cpu_get_code( &this->cpu, addr ); 25 int result = *Cpu_get_code( &this->cpu, addr );
26 if ( (unsigned) (addr - io_addr) < io_size ) 26 if ( (unsigned) (addr - io_addr) < io_size )
@@ -29,19 +29,19 @@ int Read_mem( struct Gbs_Emu* this, addr_t addr )
29 return LOG_MEM( addr, ">", result ); 29 return LOG_MEM( addr, ">", result );
30} 30}
31 31
32static inline void Write_io_inline( struct Gbs_Emu* this, int offset, int data, int base ) 32static inline void write_io_inline( struct Gbs_Emu* this, int offset, int data, int base )
33{ 33{
34 if ( (unsigned) (offset - (io_addr - base)) < io_size ) 34 if ( (unsigned) (offset - (io_addr - base)) < io_size )
35 Apu_write_register( &this->apu, Time( this ), offset + base, data & 0xFF ); 35 Apu_write_register( &this->apu, Time( this ), offset + base, data & 0xFF );
36 else if ( (unsigned) (offset - (0xFF06 - base)) < 2 ) 36 else if ( (unsigned) (offset - (0xFF06 - base)) < 2 )
37 Update_timer( this ); 37 update_timer( this );
38 else if ( offset == io_base - base ) 38 else if ( offset == io_base - base )
39 this->ram [base - ram_addr + offset] = 0; // keep joypad return value 0 39 this->ram [base - ram_addr + offset] = 0; // keep joypad return value 0
40 else 40 else
41 this->ram [base - ram_addr + offset] = 0xFF; 41 this->ram [base - ram_addr + offset] = 0xFF;
42} 42}
43 43
44void Write_mem( struct Gbs_Emu* this, addr_t addr, int data ) 44void write_mem( struct Gbs_Emu* this, addr_t addr, int data )
45{ 45{
46 (void) LOG_MEM( addr, "<", data ); 46 (void) LOG_MEM( addr, "<", data );
47 47
@@ -52,11 +52,11 @@ void Write_mem( struct Gbs_Emu* this, addr_t addr, int data )
52 52
53 offset -= 0xE000 - ram_addr; 53 offset -= 0xE000 - ram_addr;
54 if ( (unsigned) offset < 0x1F80 ) 54 if ( (unsigned) offset < 0x1F80 )
55 Write_io_inline( this, offset, data, 0xE000 ); 55 write_io_inline( this, offset, data, 0xE000 );
56 } 56 }
57 else if ( (unsigned) (offset - (0x2000 - ram_addr)) < 0x2000 ) 57 else if ( (unsigned) (offset - (0x2000 - ram_addr)) < 0x2000 )
58 { 58 {
59 Set_bank( this, data & 0xFF ); 59 set_bank( this, data & 0xFF );
60 } 60 }
61#ifndef NDEBUG 61#ifndef NDEBUG
62 else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 ) 62 else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 )
@@ -66,21 +66,21 @@ void Write_mem( struct Gbs_Emu* this, addr_t addr, int data )
66#endif 66#endif
67} 67}
68 68
69static void Write_io_( struct Gbs_Emu* this, int offset, int data ) 69static void write_io_( struct Gbs_Emu* this, int offset, int data )
70{ 70{
71 Write_io_inline( this, offset, data, io_base ); 71 write_io_inline( this, offset, data, io_base );
72} 72}
73 73
74static inline void Write_io( struct Gbs_Emu* this, int offset, int data ) 74static inline void write_io( struct Gbs_Emu* this, int offset, int data )
75{ 75{
76 (void) LOG_MEM( offset + io_base, "<", data ); 76 (void) LOG_MEM( offset + io_base, "<", data );
77 77
78 this->ram [io_base - ram_addr + offset] = data; 78 this->ram [io_base - ram_addr + offset] = data;
79 if ( (unsigned) offset < 0x80 ) 79 if ( (unsigned) offset < 0x80 )
80 Write_io_( this, offset, data ); 80 write_io_( this, offset, data );
81} 81}
82 82
83static int Read_io( struct Gbs_Emu* this, int offset ) 83static int read_io( struct Gbs_Emu* this, int offset )
84{ 84{
85 int const io_base = 0xFF00; 85 int const io_base = 0xFF00;
86 int result = this->ram [io_base - ram_addr + offset]; 86 int result = this->ram [io_base - ram_addr + offset];
@@ -106,14 +106,14 @@ static int Read_io( struct Gbs_Emu* this, int offset )
106 check( out == Read_mem( emu, addr ) );\ 106 check( out == Read_mem( emu, addr ) );\
107} 107}
108 108
109#define READ_MEM( emu, addr ) Read_mem( emu, addr ) 109#define READ_MEM( emu, addr ) read_mem( emu, addr )
110#define WRITE_MEM( emu, addr, data ) Write_mem( emu, addr, data ) 110#define WRITE_MEM( emu, addr, data ) write_mem( emu, addr, data )
111 111
112#define WRITE_IO( emu, addr, data ) Write_io( emu, addr, data ) 112#define WRITE_IO( emu, addr, data ) write_io( emu, addr, data )
113#define READ_IO( emu, addr, out ) out = Read_io( emu, addr ) 113#define READ_IO( emu, addr, out ) out = read_io( emu, addr )
114 114
115#define CPU_BEGIN \ 115#define CPU_BEGIN \
116void Run_cpu( struct Gbs_Emu* this )\ 116void run_cpu( struct Gbs_Emu* this )\
117{ \ 117{ \
118 struct Gb_Cpu* cpu = &this->cpu; 118 struct Gb_Cpu* cpu = &this->cpu;
119 #include "gb_cpu_run.h" 119 #include "gb_cpu_run.h"
diff --git a/apps/codecs/libgme/gbs_emu.c b/apps/codecs/libgme/gbs_emu.c
index 640ea43a70..7a6d484673 100644
--- a/apps/codecs/libgme/gbs_emu.c
+++ b/apps/codecs/libgme/gbs_emu.c
@@ -3,7 +3,6 @@
3#include "gbs_emu.h" 3#include "gbs_emu.h"
4 4
5#include "blargg_endian.h" 5#include "blargg_endian.h"
6#include "blargg_source.h"
7 6
8/* Copyright (C) 2003-2006 Shay Green. this module is free software; you 7/* Copyright (C) 2003-2006 Shay Green. this module is free software; you
9can redistribute it and/or modify it under the terms of the GNU Lesser 8can redistribute it and/or modify it under the terms of the GNU Lesser
@@ -16,30 +15,17 @@ details. You should have received a copy of the GNU Lesser General Public
16License along with this module; if not, write to the Free Software Foundation, 15License along with this module; if not, write to the Free Software Foundation,
17Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 16Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18 17
18#include "blargg_source.h"
19 19
20const char gme_wrong_file_type [] = "Wrong file type for this emulator"; 20const char gme_wrong_file_type [] = "Wrong file type for this emulator";
21 21
22int const idle_addr = 0xF00D; 22int const idle_addr = 0xF00D;
23int const tempo_unit = 16; 23int const tempo_unit = 16;
24 24
25int const stereo = 2; // number of channels for stereo
26int const silence_max = 6; // seconds
27int const silence_threshold = 0x10;
28long const fade_block_size = 512;
29int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
30
31static void clear_track_vars( struct Gbs_Emu* this ) 25static void clear_track_vars( struct Gbs_Emu* this )
32{ 26{
33 this->current_track_ = -1; 27 this->current_track_ = -1;
34 this->out_time = 0; 28 track_stop( &this->track_filter );
35 this->emu_time = 0;
36 this->emu_track_ended_ = true;
37 this->track_ended = true;
38 this->fade_start = (blargg_long)(LONG_MAX / 2 + 1);
39 this->fade_step = 1;
40 this->silence_time = 0;
41 this->silence_count = 0;
42 this->buf_remain = 0;
43} 29}
44 30
45void Gbs_init( struct Gbs_Emu* this ) 31void Gbs_init( struct Gbs_Emu* this )
@@ -50,11 +36,13 @@ void Gbs_init( struct Gbs_Emu* this )
50 36
51 // Unload 37 // Unload
52 this->header.timer_mode = 0; 38 this->header.timer_mode = 0;
53 clear_track_vars( this );
54 39
55 this->ignore_silence = false; 40 // defaults
56 this->silence_lookahead = 6; 41 this->tfilter = *track_get_setup( &this->track_filter );
57 this->max_initial_silence = 21; 42 this->tfilter.max_initial = 21;
43 this->tfilter.lookahead = 6;
44 this->track_filter.silence_ignored_ = false;
45
58 Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) ); 46 Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) );
59 47
60 Rom_init( &this->rom, 0x4000 ); 48 Rom_init( &this->rom, 0x4000 );
@@ -67,6 +55,11 @@ void Gbs_init( struct Gbs_Emu* this )
67 55
68 // Reduce apu sound clicks? 56 // Reduce apu sound clicks?
69 Apu_reduce_clicks( &this->apu, true ); 57 Apu_reduce_clicks( &this->apu, true );
58
59 // clears fields
60 this->voice_count_ = 0;
61 this->voice_types_ = 0;
62 clear_track_vars( this );
70} 63}
71 64
72static blargg_err_t check_gbs_header( void const* header ) 65static blargg_err_t check_gbs_header( void const* header )
@@ -78,11 +71,12 @@ static blargg_err_t check_gbs_header( void const* header )
78 71
79// Setup 72// Setup
80 73
81blargg_err_t Gbs_load( struct Gbs_Emu* this, void* data, long size ) 74blargg_err_t Gbs_load_mem( struct Gbs_Emu* this, void* data, long size )
82{ 75{
83 // Unload 76 // Unload
84 this->header.timer_mode = 0; 77 this->header.timer_mode = 0;
85 this->voice_count_ = 0; 78 this->voice_count_ = 0;
79 this->track_count = 0;
86 this->m3u.size = 0; 80 this->m3u.size = 0;
87 clear_track_vars( this ); 81 clear_track_vars( this );
88 82
@@ -112,20 +106,24 @@ blargg_err_t Gbs_load( struct Gbs_Emu* this, void* data, long size )
112 Rom_set_addr( &this->rom, load_addr ); 106 Rom_set_addr( &this->rom, load_addr );
113 107
114 this->voice_count_ = osc_count; 108 this->voice_count_ = osc_count;
109 static int const types [osc_count] = {
110 wave_type+1, wave_type+2, wave_type+3, mixed_type+1
111 };
112 this->voice_types_ = types;
113
115 Apu_volume( &this->apu, this->gain_ ); 114 Apu_volume( &this->apu, this->gain_ );
116 115
117 // Change clock rate & setup buffer 116 // Change clock rate & setup buffer
118 this->clock_rate_ = 4194304; 117 this->clock_rate_ = 4194304;
119 Buffer_clock_rate( &this->stereo_buf, 4194304 ); 118 Buffer_clock_rate( &this->stereo_buf, 4194304 );
119 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count_, this->voice_types_ ) );
120 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); 120 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
121 121
122 // Post load 122 // Post load
123 Sound_set_tempo( this, this->tempo_ ); 123 Sound_set_tempo( this, this->tempo_ );
124
125 // Remute voices
126 Sound_mute_voices( this, this->mute_mask_ ); 124 Sound_mute_voices( this, this->mute_mask_ );
127 125
128 // Reset track count 126 // Set track count
129 this->track_count = this->header.track_count; 127 this->track_count = this->header.track_count;
130 return 0; 128 return 0;
131} 129}
@@ -134,7 +132,7 @@ blargg_err_t Gbs_load( struct Gbs_Emu* this, void* data, long size )
134 132
135// see gb_cpu_io.h for read/write functions 133// see gb_cpu_io.h for read/write functions
136 134
137void Set_bank( struct Gbs_Emu* this, int n ) 135void set_bank( struct Gbs_Emu* this, int n )
138{ 136{
139 addr_t addr = mask_addr( n * this->rom.bank_size, this->rom.mask ); 137 addr_t addr = mask_addr( n * this->rom.bank_size, this->rom.mask );
140 if ( addr == 0 && this->rom.size > this->rom.bank_size ) 138 if ( addr == 0 && this->rom.size > this->rom.bank_size )
@@ -142,7 +140,7 @@ void Set_bank( struct Gbs_Emu* this, int n )
142 Cpu_map_code( &this->cpu, this->rom.bank_size, this->rom.bank_size, Rom_at_addr( &this->rom, addr ) ); 140 Cpu_map_code( &this->cpu, this->rom.bank_size, this->rom.bank_size, Rom_at_addr( &this->rom, addr ) );
143} 141}
144 142
145void Update_timer( struct Gbs_Emu* this ) 143void update_timer( struct Gbs_Emu* this )
146{ 144{
147 this->play_period = 70224 / tempo_unit; /// 59.73 Hz 145 this->play_period = 70224 / tempo_unit; /// 59.73 Hz
148 146
@@ -161,21 +159,21 @@ void Update_timer( struct Gbs_Emu* this )
161 159
162// Jumps to routine, given pointer to address in file header. Pushes idle_addr 160// Jumps to routine, given pointer to address in file header. Pushes idle_addr
163// as return address, NOT old PC. 161// as return address, NOT old PC.
164void Jsr_then_stop( struct Gbs_Emu* this, byte const addr [] ) 162void jsr_then_stop( struct Gbs_Emu* this, byte const addr [] )
165{ 163{
166 check( this->cpu.r.sp == get_le16( this->header.stack_ptr ) ); 164 check( this->cpu.r.sp == get_le16( this->header.stack_ptr ) );
167 this->cpu.r.pc = get_le16( addr ); 165 this->cpu.r.pc = get_le16( addr );
168 Write_mem( this, --this->cpu.r.sp, idle_addr >> 8 ); 166 write_mem( this, --this->cpu.r.sp, idle_addr >> 8 );
169 Write_mem( this, --this->cpu.r.sp, idle_addr ); 167 write_mem( this, --this->cpu.r.sp, idle_addr );
170} 168}
171 169
172static blargg_err_t Run_until( struct Gbs_Emu* this, int end ) 170static blargg_err_t run_until( struct Gbs_Emu* this, int end )
173{ 171{
174 this->end_time = end; 172 this->end_time = end;
175 Cpu_set_time( &this->cpu, Cpu_time( &this->cpu ) - end ); 173 Cpu_set_time( &this->cpu, Cpu_time( &this->cpu ) - end );
176 while ( true ) 174 while ( true )
177 { 175 {
178 Run_cpu( this ); 176 run_cpu( this );
179 if ( Cpu_time( &this->cpu ) >= 0 ) 177 if ( Cpu_time( &this->cpu ) >= 0 )
180 break; 178 break;
181 179
@@ -190,7 +188,7 @@ static blargg_err_t Run_until( struct Gbs_Emu* this, int end )
190 if ( Cpu_time( &this->cpu ) < this->next_play - this->end_time ) 188 if ( Cpu_time( &this->cpu ) < this->next_play - this->end_time )
191 Cpu_set_time( &this->cpu, this->next_play - this->end_time ); 189 Cpu_set_time( &this->cpu, this->next_play - this->end_time );
192 this->next_play += this->play_period; 190 this->next_play += this->play_period;
193 Jsr_then_stop( this, this->header.play_addr ); 191 jsr_then_stop( this, this->header.play_addr );
194 } 192 }
195 else if ( this->cpu.r.pc > 0xFFFF ) 193 else if ( this->cpu.r.pc > 0xFFFF )
196 { 194 {
@@ -208,9 +206,9 @@ static blargg_err_t Run_until( struct Gbs_Emu* this, int end )
208 return 0; 206 return 0;
209} 207}
210 208
211static blargg_err_t End_frame( struct Gbs_Emu* this, int end ) 209static blargg_err_t end_frame( struct Gbs_Emu* this, int end )
212{ 210{
213 RETURN_ERR( Run_until( this, end ) ); 211 RETURN_ERR( run_until( this, end ) );
214 212
215 this->next_play -= end; 213 this->next_play -= end;
216 if ( this->next_play < 0 ) // happens when play routine takes too long 214 if ( this->next_play < 0 ) // happens when play routine takes too long
@@ -226,16 +224,19 @@ static blargg_err_t End_frame( struct Gbs_Emu* this, int end )
226 return 0; 224 return 0;
227} 225}
228 226
229blargg_err_t Run_clocks( struct Gbs_Emu* this, blip_time_t duration ) 227blargg_err_t run_clocks( struct Gbs_Emu* this, blip_time_t duration )
230{ 228{
231 return End_frame( this, duration ); 229 return end_frame( this, duration );
232} 230}
233 231
234static blargg_err_t play_( struct Gbs_Emu* this, long count, sample_t* out ) 232blargg_err_t play_( void* emu, int count, sample_t* out )
235{ 233{
236 long remain = count; 234 struct Gbs_Emu* this = (struct Gbs_Emu*) emu;
235
236 int remain = count;
237 while ( remain ) 237 while ( remain )
238 { 238 {
239 Buffer_disable_immediate_removal( &this->stereo_buf );
239 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain ); 240 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
240 if ( remain ) 241 if ( remain )
241 { 242 {
@@ -247,8 +248,8 @@ static blargg_err_t play_( struct Gbs_Emu* this, long count, sample_t* out )
247 Sound_mute_voices( this, this->mute_mask_ ); 248 Sound_mute_voices( this, this->mute_mask_ );
248 } 249 }
249 int msec = Buffer_length( &this->stereo_buf ); 250 int msec = Buffer_length( &this->stereo_buf );
250 blip_time_t clocks_emulated = (blargg_long) msec * this->clock_rate_ / 1000; 251 blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
251 RETURN_ERR( Run_clocks( this, clocks_emulated ) ); 252 RETURN_ERR( run_clocks( this, clocks_emulated ) );
252 assert( clocks_emulated ); 253 assert( clocks_emulated );
253 Buffer_end_frame( &this->stereo_buf, clocks_emulated ); 254 Buffer_end_frame( &this->stereo_buf, clocks_emulated );
254 } 255 }
@@ -256,7 +257,7 @@ static blargg_err_t play_( struct Gbs_Emu* this, long count, sample_t* out )
256 return 0; 257 return 0;
257} 258}
258 259
259blargg_err_t Gbs_set_sample_rate( struct Gbs_Emu* this, long rate ) 260blargg_err_t Gbs_set_sample_rate( struct Gbs_Emu* this, int rate )
260{ 261{
261 require( !this->sample_rate_ ); // sample rate can't be changed once set 262 require( !this->sample_rate_ ); // sample rate can't be changed once set
262 Buffer_init( &this->stereo_buf ); 263 Buffer_init( &this->stereo_buf );
@@ -266,6 +267,8 @@ blargg_err_t Gbs_set_sample_rate( struct Gbs_Emu* this, long rate )
266 Buffer_bass_freq( &this->stereo_buf, 300 ); 267 Buffer_bass_freq( &this->stereo_buf, 300 );
267 268
268 this->sample_rate_ = rate; 269 this->sample_rate_ = rate;
270 RETURN_ERR( track_init( &this->track_filter, this ) );
271 this->tfilter.max_silence = 6 * stereo * this->sample_rate_;
269 return 0; 272 return 0;
270} 273}
271 274
@@ -296,7 +299,7 @@ void Sound_mute_voices( struct Gbs_Emu* this, int mask )
296 } 299 }
297 else 300 else
298 { 301 {
299 struct channel_t ch = Buffer_channel( &this->stereo_buf ); 302 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
300 assert( (ch.center && ch.left && ch.right) || 303 assert( (ch.center && ch.left && ch.right) ||
301 (!ch.center && !ch.left && !ch.right) ); // all or nothing 304 (!ch.center && !ch.left && !ch.right) ); // all or nothing
302 Apu_set_output( &this->apu, i, ch.center, ch.left, ch.right ); 305 Apu_set_output( &this->apu, i, ch.center, ch.left, ch.right );
@@ -315,10 +318,9 @@ void Sound_set_tempo( struct Gbs_Emu* this, int t )
315 318
316 this->tempo = (int) ((tempo_unit * FP_ONE_TEMPO) / t); 319 this->tempo = (int) ((tempo_unit * FP_ONE_TEMPO) / t);
317 Apu_set_tempo( &this->apu, t ); 320 Apu_set_tempo( &this->apu, t );
318 Update_timer( this ); 321 update_timer( this );
319} 322}
320 323
321void fill_buf( struct Gbs_Emu* this );
322blargg_err_t Gbs_start_track( struct Gbs_Emu* this, int track ) 324blargg_err_t Gbs_start_track( struct Gbs_Emu* this, int track )
323{ 325{
324 clear_track_vars( this ); 326 clear_track_vars( this );
@@ -330,7 +332,6 @@ blargg_err_t Gbs_start_track( struct Gbs_Emu* this, int track )
330 } 332 }
331 333
332 this->current_track_ = track; 334 this->current_track_ = track;
333
334 Buffer_clear( &this->stereo_buf ); 335 Buffer_clear( &this->stereo_buf );
335 336
336 // Reset APU to state expected by most rips 337 // Reset APU to state expected by most rips
@@ -364,268 +365,88 @@ blargg_err_t Gbs_start_track( struct Gbs_Emu* this, int track )
364 Cpu_reset( &this->cpu, this->rom.unmapped ); 365 Cpu_reset( &this->cpu, this->rom.unmapped );
365 Cpu_map_code( &this->cpu, ram_addr, 0x10000 - ram_addr, this->ram ); 366 Cpu_map_code( &this->cpu, ram_addr, 0x10000 - ram_addr, this->ram );
366 Cpu_map_code( &this->cpu, 0, this->rom.bank_size, Rom_at_addr( &this->rom, 0 ) ); 367 Cpu_map_code( &this->cpu, 0, this->rom.bank_size, Rom_at_addr( &this->rom, 0 ) );
367 Set_bank( this, this->rom.size > this->rom.bank_size ); 368 set_bank( this, this->rom.size > this->rom.bank_size );
368 369
369 Update_timer( this ); 370 update_timer( this );
370 this->next_play = this->play_period; 371 this->next_play = this->play_period;
371 this->cpu.r.rp.fa = track; 372 this->cpu.r.rp.fa = track;
372 this->cpu.r.sp = get_le16( this->header.stack_ptr ); 373 this->cpu.r.sp = get_le16( this->header.stack_ptr );
373 this->cpu_time = 0; 374 this->cpu_time = 0;
374 Jsr_then_stop( this, this->header.init_addr ); 375 jsr_then_stop( this, this->header.init_addr );
375 376
376 this->emu_track_ended_ = false; 377 // convert filter times to samples
377 this->track_ended = false; 378 struct setup_t s = this->tfilter;
379 s.max_initial *= this->sample_rate_ * stereo;
380 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
381 s.lookahead = 1;
382 #endif
383 track_setup( &this->track_filter, &s );
378 384
379 if ( !this->ignore_silence ) 385 return track_start( &this->track_filter );
380 {
381 // play until non-silence or end of track
382 long end;
383 for ( end = this->max_initial_silence * stereo * this->sample_rate_; this->emu_time < end; )
384 {
385 fill_buf( this );
386 if ( this->buf_remain | (int) this->emu_track_ended_ )
387 break;
388 }
389
390 this->emu_time = this->buf_remain;
391 this->out_time = 0;
392 this->silence_time = 0;
393 this->silence_count = 0;
394 }
395 /* return track_ended() ? warning() : 0; */
396 return 0;
397} 386}
398 387
399 388
400// Track 389// Track
401 390
402static blargg_long msec_to_samples( blargg_long msec, long sample_rate ) 391static int msec_to_samples( int msec, int sample_rate )
403{ 392{
404 blargg_long sec = msec / 1000; 393 int sec = msec / 1000;
405 msec -= sec * 1000; 394 msec -= sec * 1000;
406 return (sec * sample_rate + msec * sample_rate / 1000) * stereo; 395 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
407} 396}
408 397
409long Track_tell( struct Gbs_Emu* this ) 398int Track_tell( struct Gbs_Emu* this )
410{ 399{
411 blargg_long rate = this->sample_rate_ * stereo; 400 int rate = this->sample_rate_ * stereo;
412 blargg_long sec = this->out_time / rate; 401 int sec = track_sample_count( &this->track_filter ) / rate;
413 return sec * 1000 + (this->out_time - sec * rate) * 1000 / rate; 402 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
414} 403}
415 404
416blargg_err_t Track_seek( struct Gbs_Emu* this, long msec ) 405blargg_err_t Track_seek( struct Gbs_Emu* this, int msec )
417{ 406{
418 blargg_long time = msec_to_samples( msec, this->sample_rate_ ); 407 int time = msec_to_samples( msec, this->sample_rate_ );
419 if ( time < this->out_time ) 408 if ( time < track_sample_count( &this->track_filter ) )
420 RETURN_ERR( Gbs_start_track( this, this->current_track_ ) ); 409 RETURN_ERR( Gbs_start_track( this, this->current_track_ ) );
421 return Track_skip( this, time - this->out_time ); 410 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
422} 411}
423 412
424static blargg_err_t skip_( struct Gbs_Emu* this, long count ) 413blargg_err_t skip_( void* emu, int count )
425{ 414{
415 struct Gbs_Emu* this = (struct Gbs_Emu*) emu;
416
426 // for long skip, mute sound 417 // for long skip, mute sound
427 const long threshold = 30000; 418 const int threshold = 32768;
428 if ( count > threshold ) 419 if ( count > threshold )
429 { 420 {
430 int saved_mute = this->mute_mask_; 421 int saved_mute = this->mute_mask_;
431 Sound_mute_voices( this, ~0 ); 422 Sound_mute_voices( this, ~0 );
432
433 while ( count > threshold / 2 && !this->emu_track_ended_ )
434 {
435 RETURN_ERR( play_( this, buf_size, this->buf ) );
436 count -= buf_size;
437 }
438
439 Sound_mute_voices( this, saved_mute );
440 }
441
442 while ( count && !this->emu_track_ended_ )
443 {
444 long n = buf_size;
445 if ( n > count )
446 n = count;
447 count -= n;
448 RETURN_ERR( play_( this, n, this->buf ) );
449 }
450 return 0;
451}
452 423
453blargg_err_t Track_skip( struct Gbs_Emu* this, long count ) 424 int n = count - threshold/2;
454{ 425 n &= ~(2048-1); // round to multiple of 2048
455 require( this->current_track_ >= 0 ); // start_track() must have been called already
456 this->out_time += count;
457
458 // remove from silence and buf first
459 {
460 long n = min( count, this->silence_count );
461 this->silence_count -= n;
462 count -= n;
463
464 n = min( count, this->buf_remain );
465 this->buf_remain -= n;
466 count -= n; 426 count -= n;
467 } 427 RETURN_ERR( skippy_( &this->track_filter, n ) );
468
469 if ( count && !this->emu_track_ended_ )
470 {
471 this->emu_time += count;
472 // End track if error
473 if ( skip_( this, count ) )
474 this->emu_track_ended_ = true;
475 }
476
477 if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended
478 this->track_ended |= this->emu_track_ended_;
479
480 return 0;
481}
482
483// Fading
484 428
485void Track_set_fade( struct Gbs_Emu* this, long start_msec, long length_msec ) 429 Sound_mute_voices( this, saved_mute );
486{
487 this->fade_step = this->sample_rate_ * length_msec / (fade_block_size * fade_shift * 1000 / stereo);
488 this->fade_start = msec_to_samples( start_msec, this->sample_rate_ );
489}
490
491// unit / pow( 2.0, (double) x / step )
492static int int_log( blargg_long x, int step, int unit )
493{
494 int shift = x / step;
495 int fraction = (x - shift * step) * unit / step;
496 return ((unit - fraction) + (fraction >> 1)) >> shift;
497}
498
499static void handle_fade( struct Gbs_Emu* this, long out_count, sample_t* out )
500{
501 int i;
502 for ( i = 0; i < out_count; i += fade_block_size )
503 {
504 int const shift = 14;
505 int const unit = 1 << shift;
506 int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size,
507 this->fade_step, unit );
508 if ( gain < (unit >> fade_shift) )
509 this->track_ended = this->emu_track_ended_ = true;
510
511 sample_t* io = &out [i];
512 int count;
513 for ( count = min( fade_block_size, out_count - i ); count; --count )
514 {
515 *io = (sample_t) ((*io * gain) >> shift);
516 ++io;
517 }
518 } 430 }
519}
520
521// Silence detection
522 431
523static void emu_play( struct Gbs_Emu* this, long count, sample_t* out ) 432 return skippy_( &this->track_filter, count );
524{
525 check( current_track_ >= 0 );
526 this->emu_time += count;
527 if ( this->current_track_ >= 0 && !this->emu_track_ended_ ) {
528 // End track if error
529 if ( play_( this, count, out ) ) this->emu_track_ended_ = true;
530 }
531 else
532 memset( out, 0, count * sizeof *out );
533} 433}
534 434
535// number of consecutive silent samples at end 435blargg_err_t Track_skip( struct Gbs_Emu* this, int count )
536static long count_silence( sample_t* begin, long size )
537{ 436{
538 sample_t first = *begin; 437 require( this->current_track_ >= 0 ); // start_track() must have been called already
539 *begin = silence_threshold; // sentinel 438 return track_skip( &this->track_filter, count );
540 sample_t* p = begin + size;
541 while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
542 *begin = first;
543 return size - (p - begin);
544} 439}
545 440
546// fill internal buffer and check it for silence 441void Track_set_fade( struct Gbs_Emu* this, int start_msec, int length_msec )
547void fill_buf( struct Gbs_Emu* this )
548{ 442{
549 assert( !this->buf_remain ); 443 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate_ ),
550 if ( !this->emu_track_ended_ ) 444 length_msec * this->sample_rate_ / (1000 / stereo) );
551 {
552 emu_play( this, buf_size, this->buf );
553 long silence = count_silence( this->buf, buf_size );
554 if ( silence < buf_size )
555 {
556 this->silence_time = this->emu_time - silence;
557 this->buf_remain = buf_size;
558 return;
559 }
560 }
561 this->silence_count += buf_size;
562} 445}
563 446
564blargg_err_t Gbs_play( struct Gbs_Emu* this, long out_count, sample_t* out ) 447blargg_err_t Gbs_play( struct Gbs_Emu* this, int out_count, sample_t* out )
565{ 448{
566 if ( this->track_ended ) 449 require( this->current_track_ >= 0 );
567 { 450 require( out_count % stereo == 0 );
568 memset( out, 0, out_count * sizeof *out ); 451 return track_play( &this->track_filter, out_count, out );
569 }
570 else
571 {
572 require( this->current_track_ >= 0 );
573 require( out_count % stereo == 0 );
574
575 assert( this->emu_time >= this->out_time );
576
577 long pos = 0;
578 if ( this->silence_count )
579 {
580 // during a run of silence, run emulator at >=2x speed so it gets ahead
581 long ahead_time = this->silence_lookahead * (this->out_time + out_count - this->silence_time) + this->silence_time;
582 while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) )
583 fill_buf( this );
584
585 // fill with silence
586 pos = min( this->silence_count, out_count );
587 memset( out, 0, pos * sizeof *out );
588 this->silence_count -= pos;
589
590 if ( this->emu_time - this->silence_time > silence_max * stereo * this->sample_rate_ )
591 {
592 this->track_ended = this->emu_track_ended_ = true;
593 this->silence_count = 0;
594 this->buf_remain = 0;
595 }
596 }
597
598 if ( this->buf_remain )
599 {
600 // empty silence buf
601 long n = min( this->buf_remain, out_count - pos );
602 memcpy( &out [pos], this->buf + (buf_size - this->buf_remain), n * sizeof *out );
603 this->buf_remain -= n;
604 pos += n;
605 }
606
607 // generate remaining samples normally
608 long remain = out_count - pos;
609 if ( remain )
610 {
611 emu_play( this, remain, out + pos );
612 this->track_ended |= this->emu_track_ended_;
613
614 if ( !this->ignore_silence || this->out_time > this->fade_start )
615 {
616 // check end for a new run of silence
617 long silence = count_silence( out + pos, remain );
618 if ( silence < remain )
619 this->silence_time = this->emu_time - silence;
620
621 if ( this->emu_time - this->silence_time >= buf_size )
622 fill_buf( this ); // cause silence detection on next play()
623 }
624 }
625
626 if ( this->out_time > this->fade_start )
627 handle_fade( this, out_count, out );
628 }
629 this->out_time += out_count;
630 return 0;
631} 452}
diff --git a/apps/codecs/libgme/gbs_emu.h b/apps/codecs/libgme/gbs_emu.h
index 409cf2d6c2..72671b4658 100644
--- a/apps/codecs/libgme/gbs_emu.h
+++ b/apps/codecs/libgme/gbs_emu.h
@@ -9,15 +9,12 @@
9#include "gb_apu.h" 9#include "gb_apu.h"
10#include "gb_cpu.h" 10#include "gb_cpu.h"
11#include "m3u_playlist.h" 11#include "m3u_playlist.h"
12 12#include "track_filter.h"
13/* typedef uint8_t byte; */
14typedef short sample_t;
15 13
16enum { joypad_addr = 0xFF00 }; 14enum { joypad_addr = 0xFF00 };
17enum { ram_addr = 0xA000 }; 15enum { ram_addr = 0xA000 };
18enum { hi_page = 0xFF00 - ram_addr }; 16enum { hi_page = 0xFF00 - ram_addr };
19enum { io_base = 0xFF00 }; 17enum { io_base = 0xFF00 };
20enum { buf_size = 2048 };
21 18
22// Selects which sound hardware to use. AGB hardware is cleaner than the 19// Selects which sound hardware to use. AGB hardware is cleaner than the
23// others. Doesn't take effect until next start_track(). 20// others. Doesn't take effect until next start_track().
@@ -59,36 +56,19 @@ struct Gbs_Emu {
59 blip_time_t next_play; 56 blip_time_t next_play;
60 57
61 // Sound 58 // Sound
62 long clock_rate_; 59 int clock_rate_;
63 long sample_rate_; 60 int sample_rate_;
64 unsigned buf_changed_count; 61 unsigned buf_changed_count;
65 int voice_count_; 62 int voice_count_;
63 int const* voice_types_;
64 int mute_mask_;
66 int gain_; 65 int gain_;
67 int tempo_; 66 int tempo_;
68 67
69 // track-specific 68 // track-specific
70 byte track_count; 69 byte track_count;
71 volatile bool track_ended;
72 int current_track_; 70 int current_track_;
73 blargg_long out_time; // number of samples played since start of track
74 blargg_long emu_time; // number of samples emulator has generated since start of track
75 bool emu_track_ended_; // emulator has reached end of track
76
77 // fading
78 blargg_long fade_start;
79 int fade_step;
80
81 // silence detection
82 // Disable automatic end-of-track detection and skipping of silence at beginning
83 bool ignore_silence;
84 71
85 int max_initial_silence;
86 int mute_mask_;
87 int silence_lookahead; // speed to run emulator when looking ahead for silence
88 long silence_time; // number of samples where most recent silence began
89 long silence_count; // number of samples of silence to play before using buf
90 long buf_remain; // number of samples left in silence buffer
91
92 // Larger items at the end 72 // Larger items at the end
93 // Header for currently loaded file 73 // Header for currently loaded file
94 struct header_t header; 74 struct header_t header;
@@ -96,11 +76,12 @@ struct Gbs_Emu {
96 // M3u Playlist 76 // M3u Playlist
97 struct M3u_Playlist m3u; 77 struct M3u_Playlist m3u;
98 78
79 struct setup_t tfilter;
80 struct Track_Filter track_filter;
81
99 struct Gb_Apu apu; 82 struct Gb_Apu apu;
100 struct Gb_Cpu cpu; 83 struct Gb_Cpu cpu;
101 struct Stereo_Buffer stereo_buf; 84 struct Multi_Buffer stereo_buf;
102
103 sample_t buf [buf_size];
104 85
105 // rom & ram 86 // rom & ram
106 struct Rom_Data rom; 87 struct Rom_Data rom;
@@ -116,36 +97,48 @@ void Gbs_init( struct Gbs_Emu* this );
116void Gbs_stop( struct Gbs_Emu* this ); 97void Gbs_stop( struct Gbs_Emu* this );
117 98
118// Loads a file from memory 99// Loads a file from memory
119blargg_err_t Gbs_load( struct Gbs_Emu* this, void* data, long size ); 100blargg_err_t Gbs_load_mem( struct Gbs_Emu* this, void* data, long size );
120 101
121// Set output sample rate. Must be called only once before loading file. 102// Set output sample rate. Must be called only once before loading file.
122blargg_err_t Gbs_set_sample_rate( struct Gbs_Emu* this, long sample_rate ); 103blargg_err_t Gbs_set_sample_rate( struct Gbs_Emu* this, int sample_rate );
123 104
124// Start a track, where 0 is the first track. Also clears warning string. 105// Start a track, where 0 is the first track. Also clears warning string.
125blargg_err_t Gbs_start_track( struct Gbs_Emu* this, int ); 106blargg_err_t Gbs_start_track( struct Gbs_Emu* this, int );
126 107
127// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation 108// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
128// errors set warning string, and major errors also end track. 109// errors set warning string, and major errors also end track.
129blargg_err_t Gbs_play( struct Gbs_Emu* this, long count, sample_t* buf ); 110blargg_err_t Gbs_play( struct Gbs_Emu* this, int count, sample_t* buf );
130 111
131// Track status/control 112// Track status/control
132// Number of milliseconds (1000 msec = 1 second) played since beginning of track 113// Number of milliseconds (1000 msec = 1 second) played since beginning of track
133long Track_tell( struct Gbs_Emu* this ); 114int Track_tell( struct Gbs_Emu* this );
134 115
135// Seek to new time in track. Seeking backwards or far forward can take a while. 116// Seek to new time in track. Seeking backwards or far forward can take a while.
136blargg_err_t Track_seek( struct Gbs_Emu* this, long msec ); 117blargg_err_t Track_seek( struct Gbs_Emu* this, int msec );
137 118
138// Skip n samples 119// Skip n samples
139blargg_err_t Track_skip( struct Gbs_Emu* this, long n ); 120blargg_err_t Track_skip( struct Gbs_Emu* this, int n );
140 121
141// Set start time and length of track fade out. Once fade ends track_ended() returns 122// Set start time and length of track fade out. Once fade ends track_ended() returns
142// true. Fade time can be changed while track is playing. 123// true. Fade time can be changed while track is playing.
143void Track_set_fade( struct Gbs_Emu* this, long start_msec, long length_msec ); 124void Track_set_fade( struct Gbs_Emu* this, int start_msec, int length_msec );
125
126// True if a track has reached its end
127static inline bool Track_ended( struct Gbs_Emu* this )
128{
129 return track_ended( &this->track_filter );
130}
131
132// Disables automatic end-of-track detection and skipping of silence at beginning
133static inline void Track_ignore_silence( struct Gbs_Emu* this, bool disable )
134{
135 this->track_filter.silence_ignored_ = disable;
136}
144 137
145// Get track length in milliseconds 138// Get track length in milliseconds
146static inline long Track_get_length( struct Gbs_Emu* this, int n ) 139static inline int Track_get_length( struct Gbs_Emu* this, int n )
147{ 140{
148 long length = 120 * 1000; /* 2 minutes */ 141 int length = 120 * 1000; /* 2 minutes */
149 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) { 142 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
150 struct entry_t* entry = &this->m3u.entries [n]; 143 struct entry_t* entry = &this->m3u.entries [n];
151 length = entry->length; 144 length = entry->length;
@@ -175,19 +168,18 @@ static inline void Sound_set_gain( struct Gbs_Emu* this, int g )
175 this->gain_ = g; 168 this->gain_ = g;
176} 169}
177 170
178
179// Emulation (You shouldn't touch these) 171// Emulation (You shouldn't touch these)
180 172
181blargg_err_t Run_clocks( struct Gbs_Emu* this, blip_time_t duration ); 173blargg_err_t run_clocks( struct Gbs_Emu* this, blip_time_t duration );
182void Set_bank( struct Gbs_Emu* this, int ); 174void set_bank( struct Gbs_Emu* this, int );
183void Update_timer( struct Gbs_Emu* this ); 175void update_timer( struct Gbs_Emu* this );
184 176
185// Runs CPU until time becomes >= 0 177// Runs CPU until time becomes >= 0
186void Run_cpu( struct Gbs_Emu* this ); 178void run_cpu( struct Gbs_Emu* this );
187 179
188// Reads/writes memory and I/O 180// Reads/writes memory and I/O
189int Read_mem( struct Gbs_Emu* this, addr_t addr ); 181int read_mem( struct Gbs_Emu* this, addr_t addr );
190void Write_mem( struct Gbs_Emu* this, addr_t addr, int data ); 182void write_mem( struct Gbs_Emu* this, addr_t addr, int data );
191 183
192// Current time 184// Current time
193static inline blip_time_t Time( struct Gbs_Emu* this ) 185static inline blip_time_t Time( struct Gbs_Emu* this )
@@ -195,6 +187,6 @@ static inline blip_time_t Time( struct Gbs_Emu* this )
195 return Cpu_time( &this->cpu ) + this->end_time; 187 return Cpu_time( &this->cpu ) + this->end_time;
196} 188}
197 189
198void Jsr_then_stop( struct Gbs_Emu* this, byte const [] ); 190void jsr_then_stop( struct Gbs_Emu* this, byte const [] );
199 191
200#endif 192#endif
diff --git a/apps/codecs/libgme/gme_types.h b/apps/codecs/libgme/gme_types.h
deleted file mode 100644
index 06226f4aa1..0000000000
--- a/apps/codecs/libgme/gme_types.h
+++ /dev/null
@@ -1,21 +0,0 @@
1#ifndef GME_TYPES_H
2#define GME_TYPES_H
3
4/*
5 * This is a default gme_types.h for use when *not* using
6 * CMake. If CMake is in use gme_types.h.in will be
7 * processed instead.
8 */
9#define USE_GME_AY
10#define USE_GME_GBS
11#define USE_GME_GYM
12#define USE_GME_HES
13#define USE_GME_KSS
14#define USE_GME_NSF
15#define USE_GME_NSFE
16#define USE_GME_SAP
17#define USE_GME_SPC
18/* VGM and VGZ are a package deal */
19#define USE_GME_VGM
20
21#endif /* GME_TYPES_H */
diff --git a/apps/codecs/libgme/hes_apu.c b/apps/codecs/libgme/hes_apu.c
index 2a831426f5..054b164a9a 100644
--- a/apps/codecs/libgme/hes_apu.c
+++ b/apps/codecs/libgme/hes_apu.c
@@ -18,8 +18,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18 18
19enum { center_waves = 1 }; // reduces asymmetry and clamping when starting notes 19enum { center_waves = 1 }; // reduces asymmetry and clamping when starting notes
20 20
21static void Apu_balance_changed( struct Hes_Apu* this, struct Hes_Osc* osc ); 21static void balance_changed( struct Hes_Apu* this, struct Hes_Osc* osc )
22static void Apu_balance_changed( struct Hes_Apu* this, struct Hes_Osc* osc )
23{ 22{
24 static short const log_table [32] = { // ~1.5 db per step 23 static short const log_table [32] = { // ~1.5 db per step
25 #define ENTRY( factor ) (short) (factor * amp_range / 31.0 + 0.5) 24 #define ENTRY( factor ) (short) (factor * amp_range / 31.0 + 0.5)
@@ -42,27 +41,40 @@ static void Apu_balance_changed( struct Hes_Apu* this, struct Hes_Osc* osc )
42 int right = vol + (osc->balance << 1 & 0x1E) + (this->balance << 1 & 0x1E); 41 int right = vol + (osc->balance << 1 & 0x1E) + (this->balance << 1 & 0x1E);
43 if ( right < 0 ) right = 0; 42 if ( right < 0 ) right = 0;
44 43
45 left = log_table [left ];
46 right = log_table [right];
47
48 // optimizing for the common case of being centered also allows easy 44 // optimizing for the common case of being centered also allows easy
49 // panning using Effects_Buffer 45 // panning using Effects_Buffer
50 osc->outputs [0] = osc->chans [0]; // center 46
51 osc->outputs [1] = 0; 47 // Separate balance into center volume and additional on either left or right
52 if ( left != right ) 48 osc->output [0] = osc->outputs [0]; // center
49 osc->output [1] = osc->outputs [2]; // right
50 int base = log_table [left ];
51 int side = log_table [right] - base;
52 if ( side < 0 )
53 {
54 base += side;
55 side = -side;
56 osc->output [1] = osc->outputs [1]; // left
57 }
58
59 // Optimize when output is far left, center, or far right
60 if ( !base || osc->output [0] == osc->output [1] )
53 { 61 {
54 osc->outputs [0] = osc->chans [1]; // left 62 base += side;
55 osc->outputs [1] = osc->chans [2]; // right 63 side = 0;
64 osc->output [0] = osc->output [1];
65 osc->output [1] = NULL;
66 osc->last_amp [1] = 0;
56 } 67 }
57 68
58 if ( center_waves ) 69 if ( center_waves )
59 { 70 {
60 osc->last_amp [0] += (left - osc->volume [0]) * 16; 71 // TODO: this can leave a non-zero level in a buffer (minor)
61 osc->last_amp [1] += (right - osc->volume [1]) * 16; 72 osc->last_amp [0] += (base - osc->volume [0]) * 16;
73 osc->last_amp [1] += (side - osc->volume [1]) * 16;
62 } 74 }
63 75
64 osc->volume [0] = left; 76 osc->volume [0] = base;
65 osc->volume [1] = right; 77 osc->volume [1] = side;
66} 78}
67 79
68void Apu_init( struct Hes_Apu* this ) 80void Apu_init( struct Hes_Apu* this )
@@ -71,11 +83,11 @@ void Apu_init( struct Hes_Apu* this )
71 do 83 do
72 { 84 {
73 osc--; 85 osc--;
74 osc->outputs [0] = 0; 86 osc->output [0] = NULL;
75 osc->outputs [1] = 0; 87 osc->output [1] = NULL;
76 osc->chans [0] = 0; 88 osc->outputs [0] = NULL;
77 osc->chans [1] = 0; 89 osc->outputs [1] = NULL;
78 osc->chans [2] = 0; 90 osc->outputs [2] = NULL;
79 } 91 }
80 while ( osc != this->oscs ); 92 while ( osc != this->oscs );
81 93
@@ -92,139 +104,183 @@ void Apu_reset( struct Hes_Apu* this )
92 { 104 {
93 osc--; 105 osc--;
94 memset( osc, 0, offsetof (struct Hes_Osc,outputs) ); 106 memset( osc, 0, offsetof (struct Hes_Osc,outputs) );
95 osc->noise_lfsr = 1; 107 osc->lfsr = 1;
96 osc->control = 0x40; 108 osc->control = 0x40;
97 osc->balance = 0xFF; 109 osc->balance = 0xFF;
98 } 110 }
99 while ( osc != this->oscs ); 111 while ( osc != this->oscs );
112
113 // Only last two oscs support noise
114 this->oscs [osc_count - 2].lfsr = 0x200C3; // equivalent to 1 in Fibonacci LFSR
115 this->oscs [osc_count - 1].lfsr = 0x200C3;
100} 116}
101 117
102void Apu_osc_output( struct Hes_Apu* this, int index, struct Blip_Buffer* center, struct Blip_Buffer* left, struct Blip_Buffer* right ) 118void Apu_osc_output( struct Hes_Apu* this, int i, struct Blip_Buffer* center, struct Blip_Buffer* left, struct Blip_Buffer* right )
103{ 119{
104 require( (unsigned) index < osc_count ); 120 // Must be silent (all NULL), mono (left and right NULL), or stereo (none NULL)
105 this->oscs [index].chans [0] = center; 121 require( !center || (center && !left && !right) || (center && left && right) );
106 this->oscs [index].chans [1] = left; 122 require( (unsigned) i < osc_count ); // fails if you pass invalid osc index
107 this->oscs [index].chans [2] = right;
108 123
109 struct Hes_Osc* osc = &this->oscs [osc_count]; 124 if ( !center || !left || !right )
110 do
111 { 125 {
112 osc--; 126 left = center;
113 Apu_balance_changed( this, osc ); 127 right = center;
114 } 128 }
115 while ( osc != this->oscs ); 129
130 struct Hes_Osc* o = &this->oscs [i];
131 o->outputs [0] = center;
132 o->outputs [1] = right;
133 o->outputs [2] = left;
134 balance_changed( this, o );
116} 135}
117 136
118void Osc_run_until( struct Hes_Osc* this, struct Blip_Synth* synth_, blip_time_t end_time ) 137void run_osc( struct Hes_Osc* o, struct Blip_Synth* syn, blip_time_t end_time )
119{ 138{
120 struct Blip_Buffer* const osc_outputs_0 = this->outputs [0]; // cache often-used values 139 int vol0 = o->volume [0];
121 if ( osc_outputs_0 && this->control & 0x80 ) 140 int vol1 = o->volume [1];
141 int dac = o->dac;
142
143 struct Blip_Buffer* out0 = o->output [0]; // cache often-used values
144 struct Blip_Buffer* out1 = o->output [1];
145 if ( !(o->control & 0x80) )
146 out0 = NULL;
147
148 if ( out0 )
122 { 149 {
123 int dac = this->dac; 150 // Update amplitudes
124 151 if ( out1 )
125 int const volume_0 = this->volume [0];
126 { 152 {
127 int delta = dac * volume_0 - this->last_amp [0]; 153 int delta = dac * vol1 - o->last_amp [1];
128 if ( delta ) 154 if ( delta )
129 Synth_offset( synth_, this->last_time, delta, osc_outputs_0 ); 155 {
130 Blip_set_modified( osc_outputs_0 ); 156 Synth_offset( syn, o->last_time, delta, out1 );
157 Blip_set_modified( out1 );
158 }
131 } 159 }
132 160 int delta = dac * vol0 - o->last_amp [0];
133 struct Blip_Buffer* const osc_outputs_1 = this->outputs [1]; 161 if ( delta )
134 int const volume_1 = this->volume [1];
135 if ( osc_outputs_1 )
136 { 162 {
137 int delta = dac * volume_1 - this->last_amp [1]; 163 Synth_offset( syn, o->last_time, delta, out0 );
138 if ( delta ) 164 Blip_set_modified( out0 );
139 Synth_offset( synth_, this->last_time, delta, osc_outputs_1 );
140 Blip_set_modified( osc_outputs_1 );
141 } 165 }
142 166
143 blip_time_t time = this->last_time + this->delay; 167 // Don't generate if silent
168 if ( !(vol0 | vol1) )
169 out0 = NULL;
170 }
171
172 // Generate noise
173 int noise = 0;
174 if ( o->lfsr )
175 {
176 noise = o->noise & 0x80;
177
178 blip_time_t time = o->last_time + o->noise_delay;
144 if ( time < end_time ) 179 if ( time < end_time )
145 { 180 {
146 if ( this->noise & 0x80 ) 181 int period = (~o->noise & 0x1F) * 128;
182 if ( !period )
183 period = 64;
184
185 if ( noise && out0 )
147 { 186 {
148 if ( volume_0 | volume_1 ) 187 unsigned lfsr = o->lfsr;
188 do
149 { 189 {
150 // noise 190 int new_dac = -(lfsr & 1);
151 int const period = (32 - (this->noise & 0x1F)) * 64; // TODO: correct? 191 lfsr = (lfsr >> 1) ^ (0x30061 & new_dac);
152 unsigned noise_lfsr = this->noise_lfsr; 192
153 do 193 int delta = (new_dac &= 0x1F) - dac;
194 if ( delta )
154 { 195 {
155 int new_dac = 0x1F & -(noise_lfsr >> 1 & 1); 196 dac = new_dac;
156 // Implemented using "Galios configuration" 197 Synth_offset( syn, time, delta * vol0, out0 );
157 // TODO: find correct LFSR algorithm 198 if ( out1 )
158 noise_lfsr = (noise_lfsr >> 1) ^ (0xE008 & -(noise_lfsr & 1)); 199 Synth_offset( syn, time, delta * vol1, out1 );
159 //noise_lfsr = (noise_lfsr >> 1) ^ (0x6000 & -(noise_lfsr & 1));
160 int delta = new_dac - dac;
161 if ( delta )
162 {
163 dac = new_dac;
164 Synth_offset( synth_, time, delta * volume_0, osc_outputs_0 );
165 if ( osc_outputs_1 )
166 Synth_offset( synth_, time, delta * volume_1, osc_outputs_1 );
167 }
168 time += period;
169 } 200 }
170 while ( time < end_time ); 201 time += period;
171
172 this->noise_lfsr = noise_lfsr;
173 assert( noise_lfsr );
174 } 202 }
175 } 203 while ( time < end_time );
176 else if ( !(this->control & 0x40) ) 204
177 { 205 if ( !lfsr )
178 // wave
179 int phase = (this->phase + 1) & 0x1F; // pre-advance for optimal inner loop
180 int period = this->period * 2;
181 if ( period >= 14 && (volume_0 | volume_1) )
182 { 206 {
183 do 207 lfsr = 1;
184 { 208 check( false );
185 int new_dac = this->wave [phase];
186 phase = (phase + 1) & 0x1F;
187 int delta = new_dac - dac;
188 if ( delta )
189 {
190 dac = new_dac;
191 Synth_offset( synth_, time, delta * volume_0, osc_outputs_0 );
192 if ( osc_outputs_1 )
193 Synth_offset( synth_, time, delta * volume_1, osc_outputs_1 );
194 }
195 time += period;
196 }
197 while ( time < end_time );
198 } 209 }
199 else 210 o->lfsr = lfsr;
211
212 Blip_set_modified( out0 );
213 if ( out1 )
214 Blip_set_modified( out1 );
215 }
216 else
217 {
218 // Maintain phase when silent
219 int count = (end_time - time + period - 1) / period;
220 time += count * period;
221
222 // not worth it
223 //while ( count-- )
224 // o->lfsr = (o->lfsr >> 1) ^ (0x30061 * (o->lfsr & 1));
225 }
226 }
227 o->noise_delay = time - end_time;
228 }
229
230 // Generate wave
231 blip_time_t time = o->last_time + o->delay;
232 if ( time < end_time )
233 {
234 int phase = (o->phase + 1) & 0x1F; // pre-advance for optimal inner loop
235 int period = o->period * 2;
236
237 if ( period >= 14 && out0 && !((o->control & 0x40) | noise) )
238 {
239 do
240 {
241 int new_dac = o->wave [phase];
242 phase = (phase + 1) & 0x1F;
243 int delta = new_dac - dac;
244 if ( delta )
200 { 245 {
201 if ( !period ) 246 dac = new_dac;
202 { 247 Synth_offset( syn, time, delta * vol0, out0 );
203 // TODO: Gekisha Boy assumes that period = 0 silences wave 248 if ( out1 )
204 //period = 0x1000 * 2; 249 Synth_offset( syn, time, delta * vol1, out1 );
205 period = 1;
206 //if ( !(volume_0 | volume_1) )
207 // dprintf( "Used period 0\n" );
208 }
209
210 // maintain phase when silent
211 blargg_long count = (end_time - time + period - 1) / period;
212 phase += count; // phase will be masked below
213 time += count * period;
214 } 250 }
215 this->phase = (phase - 1) & 0x1F; // undo pre-advance 251 time += period;
216 } 252 }
253 while ( time < end_time );
254 Blip_set_modified( out0 );
255 if ( out1 )
256 Blip_set_modified( out1 );
257 }
258 else
259 {
260 // Maintain phase when silent
261 int count = end_time - time;
262 if ( !period )
263 period = 1;
264 count = (count + period - 1) / period;
265
266 phase += count; // phase will be masked below
267 time += count * period;
217 } 268 }
218 time -= end_time;
219 if ( time < 0 )
220 time = 0;
221 this->delay = time;
222 269
223 this->dac = dac; 270 // TODO: Find whether phase increments even when both volumes are zero.
224 this->last_amp [0] = dac * volume_0; 271 // CAN'T simply check for out0 being non-NULL, since it could be NULL
225 this->last_amp [1] = dac * volume_1; 272 // if channel is muted in player, but still has non-zero volume.
273 // City Hunter breaks when this check is removed.
274 if ( !(o->control & 0x40) && (vol0 | vol1) )
275 o->phase = (phase - 1) & 0x1F; // undo pre-advance
226 } 276 }
227 this->last_time = end_time; 277 o->delay = time - end_time;
278 check( o->delay >= 0 );
279
280 o->last_time = end_time;
281 o->dac = dac;
282 o->last_amp [0] = dac * vol0;
283 o->last_amp [1] = dac * vol1;
228} 284}
229 285
230void Apu_write_data( struct Hes_Apu* this, blip_time_t time, int addr, int data ) 286void Apu_write_data( struct Hes_Apu* this, blip_time_t time, int addr, int data )
@@ -243,8 +299,8 @@ void Apu_write_data( struct Hes_Apu* this, blip_time_t time, int addr, int data
243 do 299 do
244 { 300 {
245 osc--; 301 osc--;
246 Osc_run_until( osc, &this->synth, time ); 302 run_osc( osc, &this->synth, time );
247 Apu_balance_changed( this, this->oscs ); 303 balance_changed( this, this->oscs );
248 } 304 }
249 while ( osc != this->oscs ); 305 while ( osc != this->oscs );
250 } 306 }
@@ -252,7 +308,7 @@ void Apu_write_data( struct Hes_Apu* this, blip_time_t time, int addr, int data
252 else if ( this->latch < osc_count ) 308 else if ( this->latch < osc_count )
253 { 309 {
254 struct Hes_Osc* osc = &this->oscs [this->latch]; 310 struct Hes_Osc* osc = &this->oscs [this->latch];
255 Osc_run_until( osc, &this->synth, time ); 311 run_osc( osc, &this->synth, time );
256 switch ( addr ) 312 switch ( addr )
257 { 313 {
258 case 0x802: 314 case 0x802:
@@ -267,12 +323,12 @@ void Apu_write_data( struct Hes_Apu* this, blip_time_t time, int addr, int data
267 if ( osc->control & 0x40 & ~data ) 323 if ( osc->control & 0x40 & ~data )
268 osc->phase = 0; 324 osc->phase = 0;
269 osc->control = data; 325 osc->control = data;
270 Apu_balance_changed( this, osc ); 326 balance_changed( this, osc );
271 break; 327 break;
272 328
273 case 0x805: 329 case 0x805:
274 osc->balance = data; 330 osc->balance = data;
275 Apu_balance_changed( this, osc ); 331 balance_changed( this, osc );
276 break; 332 break;
277 333
278 case 0x806: 334 case 0x806:
@@ -289,9 +345,9 @@ void Apu_write_data( struct Hes_Apu* this, blip_time_t time, int addr, int data
289 break; 345 break;
290 346
291 case 0x807: 347 case 0x807:
292 if ( osc >= &this->oscs [4] ) 348 osc->noise = data;
293 osc->noise = data;
294 break; 349 break;
350
295 case 0x809: 351 case 0x809:
296 if ( !(data & 0x80) && (data & 0x03) != 0 ) { 352 if ( !(data & 0x80) && (data & 0x03) != 0 ) {
297 dprintf( "HES LFO not supported\n" ); 353 dprintf( "HES LFO not supported\n" );
@@ -307,7 +363,7 @@ void Apu_end_frame( struct Hes_Apu* this, blip_time_t end_time )
307 { 363 {
308 osc--; 364 osc--;
309 if ( end_time > osc->last_time ) 365 if ( end_time > osc->last_time )
310 Osc_run_until( osc, &this->synth, end_time ); 366 run_osc( osc, &this->synth, end_time );
311 assert( osc->last_time >= end_time ); 367 assert( osc->last_time >= end_time );
312 osc->last_time -= end_time; 368 osc->last_time -= end_time;
313 } 369 }
diff --git a/apps/codecs/libgme/hes_apu.h b/apps/codecs/libgme/hes_apu.h
index 8f8a525108..0265e6a3ad 100644
--- a/apps/codecs/libgme/hes_apu.h
+++ b/apps/codecs/libgme/hes_apu.h
@@ -5,40 +5,46 @@
5#define HES_APU_H 5#define HES_APU_H
6 6
7#include "blargg_common.h" 7#include "blargg_common.h"
8#include "blargg_source.h"
8#include "blip_buffer.h" 9#include "blip_buffer.h"
9 10
10enum { amp_range = 0x8000 }; 11enum { amp_range = 0x8000 };
11enum { osc_count = 6 }; 12enum { osc_count = 6 }; // 0 <= chan < osc_count
12enum { start_addr = 0x0800 }; 13
13enum { end_addr = 0x0809 }; 14// Registers are at io_addr to io_addr+io_size-1
15enum { apu_io_addr = 0x0800 };
16enum { apu_io_size = 10 };
14 17
15struct Hes_Osc 18struct Hes_Osc
16{ 19{
17 unsigned char wave [32]; 20 byte wave [32];
21 int delay;
22 int period;
23 int phase;
24
25 int noise_delay;
26 byte noise;
27 unsigned lfsr;
28
29 byte control;
30 byte balance;
31 byte dac;
18 short volume [2]; 32 short volume [2];
19 int last_amp [2]; 33 int last_amp [2];
20 int delay;
21 int period;
22 unsigned char noise;
23 unsigned char phase;
24 unsigned char balance;
25 unsigned char dac;
26 blip_time_t last_time;
27 34
28 struct Blip_Buffer* outputs [2]; 35 blip_time_t last_time;
29 struct Blip_Buffer* chans [3]; 36 struct Blip_Buffer* output [2];
30 unsigned noise_lfsr; 37 struct Blip_Buffer* outputs [3];
31 unsigned char control;
32}; 38};
33 39
34void Osc_run_until( struct Hes_Osc* this, struct Blip_Synth* synth, blip_time_t ); 40void Osc_run_until( struct Hes_Osc* this, struct Blip_Synth* synth, blip_time_t );
35 41
36struct Hes_Apu { 42struct Hes_Apu {
37 struct Hes_Osc oscs [osc_count];
38 43
39 int latch; 44 int latch;
40 int balance; 45 int balance;
41 struct Blip_Synth synth; 46 struct Blip_Synth synth;
47 struct Hes_Osc oscs [osc_count];
42}; 48};
43 49
44// Init HES apu sound chip 50// Init HES apu sound chip
@@ -48,7 +54,12 @@ void Apu_init( struct Hes_Apu* this );
48void Apu_reset( struct Hes_Apu* this ); 54void Apu_reset( struct Hes_Apu* this );
49 55
50void Apu_osc_output( struct Hes_Apu* this, int index, struct Blip_Buffer* center, struct Blip_Buffer* left, struct Blip_Buffer* right ); 56void Apu_osc_output( struct Hes_Apu* this, int index, struct Blip_Buffer* center, struct Blip_Buffer* left, struct Blip_Buffer* right );
57
58// Emulates to time t, then writes data to addr
51void Apu_write_data( struct Hes_Apu* this, blip_time_t, int addr, int data ); 59void Apu_write_data( struct Hes_Apu* this, blip_time_t, int addr, int data );
60
61// Emulates to time t, then subtracts t from the current time.
62// OK if previous write call had time slightly after t.
52void Apu_end_frame( struct Hes_Apu* this, blip_time_t ); 63void Apu_end_frame( struct Hes_Apu* this, blip_time_t );
53 64
54static inline void Apu_volume( struct Hes_Apu* this, int v ) { Synth_volume( &this->synth, (v*9)/5 / osc_count / amp_range ); } 65static inline void Apu_volume( struct Hes_Apu* this, int v ) { Synth_volume( &this->synth, (v*9)/5 / osc_count / amp_range ); }
diff --git a/apps/codecs/libgme/hes_apu_adpcm.h b/apps/codecs/libgme/hes_apu_adpcm.h
index 4a2afb3e2a..afe160bb9c 100644
--- a/apps/codecs/libgme/hes_apu_adpcm.h
+++ b/apps/codecs/libgme/hes_apu_adpcm.h
@@ -12,8 +12,8 @@ enum { adpcm_amp_range = 2048 };
12enum { adpcm_osc_count = 1 }; // 0 <= chan < osc_count 12enum { adpcm_osc_count = 1 }; // 0 <= chan < osc_count
13 13
14// Registers are at io_addr to io_addr+io_size-1 14// Registers are at io_addr to io_addr+io_size-1
15enum { io_addr = 0x1800 }; 15enum { adpcm_io_addr = 0x1800 };
16enum { io_size = 0x400 }; 16enum { adpcm_io_size = 0x400 };
17 17
18struct State 18struct State
19{ 19{
diff --git a/apps/codecs/libgme/hes_cpu.c b/apps/codecs/libgme/hes_cpu.c
index 74b90593f2..6b833b3b98 100644
--- a/apps/codecs/libgme/hes_cpu.c
+++ b/apps/codecs/libgme/hes_cpu.c
@@ -1,6 +1,6 @@
1// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ 1// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
2 2
3#include "hes_cpu.h" 3#include "hes_emu.h"
4 4
5#include "blargg_endian.h" 5#include "blargg_endian.h"
6 6
@@ -17,1305 +17,105 @@ details. You should have received a copy of the GNU Lesser General Public
17License along with this module; if not, write to the Free Software Foundation, 17License along with this module; if not, write to the Free Software Foundation,
18Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 18Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
19 19
20// TODO: support T flag, including clearing it at appropriate times?
21
22// all zero-page should really use whatever is at page 1, but that would
23// reduce efficiency quite a bit
24int const ram_addr = 0x2000;
25
26#define FLUSH_TIME() (void) (s.time = s_time)
27#define CACHE_TIME() (void) (s_time = s.time)
28
29#include "hes_cpu_io.h"
30
31#include "blargg_source.h" 20#include "blargg_source.h"
21#define PAGE HES_CPU_PAGE
32 22
33#ifdef BLARGG_NONPORTABLE 23int read_mem( struct Hes_Emu* this, hes_addr_t addr )
34 #define PAGE_OFFSET( addr ) (addr)
35#else
36 #define PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
37#endif
38
39// status flags
40int const st_n = 0x80;
41int const st_v = 0x40;
42int const st_t = 0x20;
43int const st_b = 0x10;
44int const st_d = 0x08;
45int const st_i = 0x04;
46int const st_z = 0x02;
47int const st_c = 0x01;
48
49void Cpu_init( struct Hes_Cpu* this )
50{ 24{
51 this->state = &this->state_; 25 check( addr < 0x10000 );
26 int result = *Cpu_get_code( &this->cpu, addr );
27 if ( this->cpu.mmr [PAGE( addr )] == 0xFF )
28 result = read_mem_( this, addr );
29 return result;
52} 30}
53 31
54void Cpu_reset( struct Hes_Cpu* this ) 32void write_mem( struct Hes_Emu* this, hes_addr_t addr, int data )
55{ 33{
56 check( this->state == &state_ ); 34 check( addr < 0x10000 );
57 this->state = &this->state_; 35 byte* out = this->write_pages [PAGE( addr )];
58 36 if ( out )
59 this->state_.time = 0; 37 out [addr & (page_size - 1)] = data;
60 this->state_.base = 0; 38 else if ( this->cpu.mmr [PAGE( addr )] == 0xFF )
61 this->irq_time = (hes_time_t)future_hes_time; 39 write_mem_( this, addr, data );
62 this->end_time = (hes_time_t)future_hes_time;
63
64 this->r.status = st_i;
65 this->r.sp = 0;
66 this->r.pc = 0;
67 this->r.a = 0;
68 this->r.x = 0;
69 this->r.y = 0;
70
71 blargg_verify_byte_order();
72} 40}
73 41
74void Cpu_set_mmr( struct Hes_Emu* this, int reg, int bank ) 42void set_mmr( struct Hes_Emu* this, int page, int bank )
75{ 43{
76 assert( (unsigned) reg <= page_count ); // allow page past end to be set 44 this->write_pages [page] = 0;
77 assert( (unsigned) bank < 0x100 ); 45 byte* data = Rom_at_addr( &this->rom, bank * page_size );
78 this->cpu.mmr [reg] = bank; 46 if ( bank >= 0x80 )
79 uint8_t const* code = CPU_SET_MMR( this, reg, bank );
80 this->cpu.state->code_map [reg] = code - PAGE_OFFSET( reg << page_shift );
81}
82
83#define TIME (s_time + s.base)
84
85#define READ( addr ) CPU_READ( this, (addr), TIME )
86#define WRITE( addr, data ) {CPU_WRITE( this, (addr), (data), TIME );}
87#define READ_LOW( addr ) (cpu->ram [(int) (addr)])
88#define WRITE_LOW( addr, data ) (void) (READ_LOW( addr ) = (data))
89#define READ_PROG( addr ) (s.code_map [(addr) >> page_shift] [PAGE_OFFSET( addr )])
90
91#define SET_SP( v ) (sp = ((v) + 1) | 0x100)
92#define GET_SP() ((sp - 1) & 0xFF)
93#define PUSH( v ) ((sp = (sp - 1) | 0x100), WRITE_LOW( sp, v ))
94
95// even on x86, using short and unsigned char was slower
96typedef int fint16;
97typedef unsigned fuint16;
98typedef unsigned fuint8;
99typedef blargg_long fint32;
100
101bool Cpu_run( struct Hes_Emu* this, hes_time_t end_time )
102{
103 bool illegal_encountered = false;
104
105 // Set cpu end time
106 struct Hes_Cpu* cpu = &this->cpu;
107 cpu->state->time += Cpu_update_end_time( cpu, cpu->r.status, (cpu->end_time = end_time), cpu->irq_time );
108
109 struct state_t s = cpu->state_;
110 cpu->state = &s;
111
112 // even on x86, using s.time in place of s_time was slower
113 fint16 s_time = s.time;
114
115 struct registers_t* r = &cpu->r;
116
117 // registers
118 fuint16 pc = r->pc;
119 fuint8 a = r->a;
120 fuint8 x = r->x;
121 fuint8 y = r->y;
122 fuint16 sp;
123 SET_SP( r->sp );
124
125 #define IS_NEG (nz & 0x8080)
126
127 #define CALC_STATUS( out ) do {\
128 out = status & (st_v | st_d | st_i);\
129 out |= ((nz >> 8) | nz) & st_n;\
130 out |= c >> 8 & st_c;\
131 if ( !(nz & 0xFF) ) out |= st_z;\
132 } while ( 0 )
133
134 #define SET_STATUS( in ) do {\
135 status = in & (st_v | st_d | st_i);\
136 nz = in << 8;\
137 c = nz;\
138 nz |= ~in & st_z;\
139 } while ( 0 )
140
141 fuint8 status;
142 fuint16 c; // carry set if (c & 0x100) != 0
143 fuint16 nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
144 {
145 fuint8 temp = r->status;
146 SET_STATUS( temp );
147 }
148
149 goto loop;
150branch_not_taken:
151 s_time -= 2;
152loop:
153
154 #ifndef NDEBUG
155 {
156 hes_time_t correct = end_time_;
157 if ( !(status & st_i) && correct > irq_time_ )
158 correct = irq_time_;
159 check( s.base == correct );
160 /*
161 static long count;
162 if ( count == 1844 ) Debugger();
163 if ( s.base != correct ) dprintf( "%ld\n", count );
164 count++;
165 */
166 }
167 #endif
168
169 check( (unsigned) GET_SP() < 0x100 );
170 check( (unsigned) a < 0x100 );
171 check( (unsigned) x < 0x100 );
172
173 uint8_t const* instr = s.code_map [pc >> page_shift];
174 fuint8 opcode;
175
176 // TODO: eliminate this special case
177 #ifdef BLARGG_NONPORTABLE
178 opcode = instr [pc];
179 pc++;
180 instr += pc;
181 #else
182 instr += PAGE_OFFSET( pc );
183 opcode = *instr++;
184 pc++;
185 #endif
186
187 // TODO: each reference lists slightly different timing values, ugh
188 static uint8_t const clock_table [256] =
189 {// 0 1 2 3 4 5 6 7 8 9 A B C D E F
190 1,7,3, 4,6,4,6,7,3,2,2,2,7,5,7,6,// 0
191 4,7,7, 4,6,4,6,7,2,5,2,2,7,5,7,6,// 1
192 7,7,3, 4,4,4,6,7,4,2,2,2,5,5,7,6,// 2
193 4,7,7, 2,4,4,6,7,2,5,2,2,5,5,7,6,// 3
194 7,7,3, 4,8,4,6,7,3,2,2,2,4,5,7,6,// 4
195 4,7,7, 5,2,4,6,7,2,5,3,2,2,5,7,6,// 5
196 7,7,2, 2,4,4,6,7,4,2,2,2,7,5,7,6,// 6
197 4,7,7,17,4,4,6,7,2,5,4,2,7,5,7,6,// 7
198 4,7,2, 7,4,4,4,7,2,2,2,2,5,5,5,6,// 8
199 4,7,7, 8,4,4,4,7,2,5,2,2,5,5,5,6,// 9
200 2,7,2, 7,4,4,4,7,2,2,2,2,5,5,5,6,// A
201 4,7,7, 8,4,4,4,7,2,5,2,2,5,5,5,6,// B
202 2,7,2,17,4,4,6,7,2,2,2,2,5,5,7,6,// C
203 4,7,7,17,2,4,6,7,2,5,3,2,2,5,7,6,// D
204 2,7,2,17,4,4,6,7,2,2,2,2,5,5,7,6,// E
205 4,7,7,17,2,4,6,7,2,5,4,2,2,5,7,6 // F
206 }; // 0x00 was 8
207
208 fuint16 data;
209 data = clock_table [opcode];
210 if ( (s_time += data) >= 0 )
211 goto possibly_out_of_time;
212almost_out_of_time:
213
214 data = *instr;
215
216 #ifdef HES_CPU_LOG_H
217 log_cpu( "new", pc - 1, opcode, instr [0], instr [1], instr [2],
218 instr [3], instr [4], instr [5] );
219 //log_opcode( opcode );
220 #endif
221
222 switch ( opcode )
223 {
224possibly_out_of_time:
225 if ( s_time < (int) data )
226 goto almost_out_of_time;
227 s_time -= data;
228 goto out_of_time;
229
230// Macros
231
232#define GET_MSB() (instr [1])
233#define ADD_PAGE( out ) (pc++, out = data + 0x100 * GET_MSB());
234#define GET_ADDR() GET_LE16( instr )
235
236// TODO: is the penalty really always added? the original 6502 was much better
237//#define PAGE_CROSS_PENALTY( lsb ) (void) (s_time += (lsb) >> 8)
238#define PAGE_CROSS_PENALTY( lsb )
239
240// Branch
241
242// TODO: more efficient way to handle negative branch that wraps PC around
243#define BRANCH( cond )\
244{\
245 fint16 offset = (int8_t) data;\
246 pc++;\
247 if ( !(cond) ) goto branch_not_taken;\
248 pc = (uint16_t) (pc + offset);\
249 goto loop;\
250}
251
252 case 0xF0: // BEQ
253 BRANCH( !((uint8_t) nz) );
254
255 case 0xD0: // BNE
256 BRANCH( (uint8_t) nz );
257
258 case 0x10: // BPL
259 BRANCH( !IS_NEG );
260
261 case 0x90: // BCC
262 BRANCH( !(c & 0x100) )
263
264 case 0x30: // BMI
265 BRANCH( IS_NEG )
266
267 case 0x50: // BVC
268 BRANCH( !(status & st_v) )
269
270 case 0x70: // BVS
271 BRANCH( status & st_v )
272
273 case 0xB0: // BCS
274 BRANCH( c & 0x100 )
275
276 case 0x80: // BRA
277 branch_taken:
278 BRANCH( true );
279
280 case 0xFF:
281 if ( pc == idle_addr + 1 )
282 goto idle_done;
283 case 0x0F: // BBRn
284 case 0x1F:
285 case 0x2F:
286 case 0x3F:
287 case 0x4F:
288 case 0x5F:
289 case 0x6F:
290 case 0x7F:
291 case 0x8F: // BBSn
292 case 0x9F:
293 case 0xAF:
294 case 0xBF:
295 case 0xCF:
296 case 0xDF:
297 case 0xEF: {
298 fuint16 t = 0x101 * READ_LOW( data );
299 t ^= 0xFF;
300 pc++;
301 data = GET_MSB();
302 BRANCH( t & (1 << (opcode >> 4)) )
303 }
304
305 case 0x4C: // JMP abs
306 pc = GET_ADDR();
307 goto loop;
308
309 case 0x7C: // JMP (ind+X)
310 data += x;
311 case 0x6C:{// JMP (ind)
312 data += 0x100 * GET_MSB();
313 pc = GET_LE16( &READ_PROG( data ) );
314 goto loop;
315 }
316
317// Subroutine
318
319 case 0x44: // BSR
320 WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
321 sp = (sp - 2) | 0x100;
322 WRITE_LOW( sp, pc );
323 goto branch_taken;
324
325 case 0x20: { // JSR
326 fuint16 temp = pc + 1;
327 pc = GET_ADDR();
328 WRITE_LOW( 0x100 | (sp - 1), temp >> 8 );
329 sp = (sp - 2) | 0x100;
330 WRITE_LOW( sp, temp );
331 goto loop;
332 }
333
334 case 0x60: // RTS
335 pc = 0x100 * READ_LOW( 0x100 | (sp - 0xFF) );
336 pc += 1 + READ_LOW( sp );
337 sp = (sp - 0xFE) | 0x100;
338 goto loop;
339
340 case 0x00: // BRK
341 goto handle_brk;
342
343// Common
344
345 case 0xBD:{// LDA abs,X
346 PAGE_CROSS_PENALTY( data + x );
347 fuint16 addr = GET_ADDR() + x;
348 pc += 2;
349 CPU_READ_FAST( this, addr, TIME, nz );
350 a = nz;
351 goto loop;
352 }
353
354 case 0x9D:{// STA abs,X
355 fuint16 addr = GET_ADDR() + x;
356 pc += 2;
357 CPU_WRITE_FAST( this, addr, a, TIME );
358 goto loop;
359 }
360
361 case 0x95: // STA zp,x
362 data = (uint8_t) (data + x);
363 case 0x85: // STA zp
364 pc++;
365 WRITE_LOW( data, a );
366 goto loop;
367
368 case 0xAE:{// LDX abs
369 fuint16 addr = GET_ADDR();
370 pc += 2;
371 CPU_READ_FAST( this, addr, TIME, nz );
372 x = nz;
373 goto loop;
374 }
375
376 case 0xA5: // LDA zp
377 a = nz = READ_LOW( data );
378 pc++;
379 goto loop;
380
381// Load/store
382
383 { 47 {
384 fuint16 addr; 48 data = 0;
385 case 0x91: // STA (ind),Y 49 switch ( bank )
386 addr = 0x100 * READ_LOW( (uint8_t) (data + 1) ); 50 {
387 addr += READ_LOW( data ) + y; 51 case 0xF8:
388 pc++; 52 data = this->ram;
389 goto sta_ptr; 53 break;
390
391 case 0x81: // STA (ind,X)
392 data = (uint8_t) (data + x);
393 case 0x92: // STA (ind)
394 addr = 0x100 * READ_LOW( (uint8_t) (data + 1) );
395 addr += READ_LOW( data );
396 pc++;
397 goto sta_ptr;
398
399 case 0x99: // STA abs,Y
400 data += y;
401 case 0x8D: // STA abs
402 addr = data + 0x100 * GET_MSB();
403 pc += 2;
404 sta_ptr:
405 CPU_WRITE_FAST( this, addr, a, TIME );
406 goto loop;
407 }
408
409 {
410 fuint16 addr;
411 case 0xA1: // LDA (ind,X)
412 data = (uint8_t) (data + x);
413 case 0xB2: // LDA (ind)
414 addr = 0x100 * READ_LOW( (uint8_t) (data + 1) );
415 addr += READ_LOW( data );
416 pc++;
417 goto a_nz_read_addr;
418
419 case 0xB1:// LDA (ind),Y
420 addr = READ_LOW( data ) + y;
421 PAGE_CROSS_PENALTY( addr );
422 addr += 0x100 * READ_LOW( (uint8_t) (data + 1) );
423 pc++;
424 goto a_nz_read_addr;
425
426 case 0xB9: // LDA abs,Y
427 data += y;
428 PAGE_CROSS_PENALTY( data );
429 case 0xAD: // LDA abs
430 addr = data + 0x100 * GET_MSB();
431 pc += 2;
432 a_nz_read_addr:
433 CPU_READ_FAST( this, addr, TIME, nz );
434 a = nz;
435 goto loop;
436 }
437
438 case 0xBE:{// LDX abs,y
439 PAGE_CROSS_PENALTY( data + y );
440 fuint16 addr = GET_ADDR() + y;
441 pc += 2;
442 FLUSH_TIME();
443 x = nz = READ( addr );
444 CACHE_TIME();
445 goto loop;
446 }
447
448 case 0xB5: // LDA zp,x
449 a = nz = READ_LOW( (uint8_t) (data + x) );
450 pc++;
451 goto loop;
452
453 case 0xA9: // LDA #imm
454 pc++;
455 a = data;
456 nz = data;
457 goto loop;
458
459// Bit operations
460
461 case 0x3C: // BIT abs,x
462 data += x;
463 case 0x2C:{// BIT abs
464 fuint16 addr;
465 ADD_PAGE( addr );
466 FLUSH_TIME();
467 nz = READ( addr );
468 CACHE_TIME();
469 goto bit_common;
470 }
471 case 0x34: // BIT zp,x
472 data = (uint8_t) (data + x);
473 case 0x24: // BIT zp
474 data = READ_LOW( data );
475 case 0x89: // BIT imm
476 nz = data;
477 bit_common:
478 pc++;
479 status &= ~st_v;
480 status |= nz & st_v;
481 if ( nz & a )
482 goto loop; // Z should be clear, and nz must be non-zero if nz & a is
483 nz <<= 8; // set Z flag without affecting N flag
484 goto loop;
485 54
486 { 55 case 0xF9:
487 fuint16 addr; 56 case 0xFA:
57 case 0xFB:
58 data = &this->sgx [(bank - 0xF9) * page_size];
59 break;
488 60
489 case 0xB3: // TST abs,x 61 default:
490 addr = GET_MSB() + x; 62 /* if ( bank != 0xFF )
491 goto tst_abs; 63 dprintf( "Unmapped bank $%02X\n", bank ); */
492 64 data = this->rom.unmapped;
493 case 0x93: // TST abs 65 goto end;
494 addr = GET_MSB(); 66 }
495 tst_abs: 67
496 addr += 0x100 * instr [2]; 68 this->write_pages [page] = data;
497 pc++;
498 FLUSH_TIME();
499 nz = READ( addr );
500 CACHE_TIME();
501 goto tst_common;
502 }
503
504 case 0xA3: // TST zp,x
505 nz = READ_LOW( (uint8_t) (GET_MSB() + x) );
506 goto tst_common;
507
508 case 0x83: // TST zp
509 nz = READ_LOW( GET_MSB() );
510 tst_common:
511 pc += 2;
512 status &= ~st_v;
513 status |= nz & st_v;
514 if ( nz & data )
515 goto loop; // Z should be clear, and nz must be non-zero if nz & data is
516 nz <<= 8; // set Z flag without affecting N flag
517 goto loop;
518
519 {
520 fuint16 addr;
521 case 0x0C: // TSB abs
522 case 0x1C: // TRB abs
523 addr = GET_ADDR();
524 pc++;
525 goto txb_addr;
526
527 // TODO: everyone lists different behaviors for the status flags, ugh
528 case 0x04: // TSB zp
529 case 0x14: // TRB zp
530 addr = data + ram_addr;
531 txb_addr:
532 FLUSH_TIME();
533 nz = a | READ( addr );
534 if ( opcode & 0x10 )
535 nz ^= a; // bits from a will already be set, so this clears them
536 status &= ~st_v;
537 status |= nz & st_v;
538 pc++;
539 WRITE( addr, nz );
540 CACHE_TIME();
541 goto loop;
542 }
543
544 case 0x07: // RMBn
545 case 0x17:
546 case 0x27:
547 case 0x37:
548 case 0x47:
549 case 0x57:
550 case 0x67:
551 case 0x77:
552 pc++;
553 READ_LOW( data ) &= ~(1 << (opcode >> 4));
554 goto loop;
555
556 case 0x87: // SMBn
557 case 0x97:
558 case 0xA7:
559 case 0xB7:
560 case 0xC7:
561 case 0xD7:
562 case 0xE7:
563 case 0xF7:
564 pc++;
565 READ_LOW( data ) |= 1 << ((opcode >> 4) - 8);
566 goto loop;
567
568// Load/store
569
570 case 0x9E: // STZ abs,x
571 data += x;
572 case 0x9C: // STZ abs
573 ADD_PAGE( data );
574 pc++;
575 FLUSH_TIME();
576 WRITE( data, 0 );
577 CACHE_TIME();
578 goto loop;
579
580 case 0x74: // STZ zp,x
581 data = (uint8_t) (data + x);
582 case 0x64: // STZ zp
583 pc++;
584 WRITE_LOW( data, 0 );
585 goto loop;
586
587 case 0x94: // STY zp,x
588 data = (uint8_t) (data + x);
589 case 0x84: // STY zp
590 pc++;
591 WRITE_LOW( data, y );
592 goto loop;
593
594 case 0x96: // STX zp,y
595 data = (uint8_t) (data + y);
596 case 0x86: // STX zp
597 pc++;
598 WRITE_LOW( data, x );
599 goto loop;
600
601 case 0xB6: // LDX zp,y
602 data = (uint8_t) (data + y);
603 case 0xA6: // LDX zp
604 data = READ_LOW( data );
605 case 0xA2: // LDX #imm
606 pc++;
607 x = data;
608 nz = data;
609 goto loop;
610
611 case 0xB4: // LDY zp,x
612 data = (uint8_t) (data + x);
613 case 0xA4: // LDY zp
614 data = READ_LOW( data );
615 case 0xA0: // LDY #imm
616 pc++;
617 y = data;
618 nz = data;
619 goto loop;
620
621 case 0xBC: // LDY abs,X
622 data += x;
623 PAGE_CROSS_PENALTY( data );
624 case 0xAC:{// LDY abs
625 fuint16 addr = data + 0x100 * GET_MSB();
626 pc += 2;
627 FLUSH_TIME();
628 y = nz = READ( addr );
629 CACHE_TIME();
630 goto loop;
631 }
632
633 {
634 fuint8 temp;
635 case 0x8C: // STY abs
636 temp = y;
637 goto store_abs;
638
639 case 0x8E: // STX abs
640 temp = x;
641 store_abs:
642 {
643 fuint16 addr = GET_ADDR();
644 pc += 2;
645 FLUSH_TIME();
646 WRITE( addr, temp );
647 CACHE_TIME();
648 goto loop;
649 }
650 } 69 }
70end:
71 Cpu_set_mmr( &this->cpu, page, bank, data );
72}
651 73
652// Compare 74#define READ_FAST( addr, out ) \
653 75{\
654 case 0xEC:{// CPX abs 76 out = READ_CODE( addr );\
655 fuint16 addr = GET_ADDR(); 77 if ( cpu->mmr [PAGE( addr )] == 0xFF )\
656 pc++; 78 {\
657 FLUSH_TIME(); 79 FLUSH_TIME();\
658 data = READ( addr ); 80 out = read_mem_( this, addr );\
659 CACHE_TIME(); 81 CACHE_TIME();\
660 goto cpx_data; 82 }\
661 } 83}
662
663 case 0xE4: // CPX zp
664 data = READ_LOW( data );
665 case 0xE0: // CPX #imm
666 cpx_data:
667 nz = x - data;
668 pc++;
669 c = ~nz;
670 nz &= 0xFF;
671 goto loop;
672
673 case 0xCC:{// CPY abs
674 fuint16 addr = GET_ADDR();
675 pc++;
676 FLUSH_TIME();
677 data = READ( addr );
678 CACHE_TIME();
679 goto cpy_data;
680 }
681
682 case 0xC4: // CPY zp
683 data = READ_LOW( data );
684 case 0xC0: // CPY #imm
685 cpy_data:
686 nz = y - data;
687 pc++;
688 c = ~nz;
689 nz &= 0xFF;
690 goto loop;
691
692// Logical
693 84
694#define ARITH_ADDR_MODES( op )\ 85#define WRITE_FAST( addr, data ) \
695 case op - 0x04: /* (ind,x) */\ 86{\
696 data = (uint8_t) (data + x);\ 87 int page = PAGE( addr );\
697 case op + 0x0D: /* (ind) */\ 88 byte* out = this->write_pages [page];\
698 data = 0x100 * READ_LOW( (uint8_t) (data + 1) ) + READ_LOW( data );\ 89 addr &= page_size - 1;\
699 goto ptr##op;\ 90 if ( out )\
700 case op + 0x0C:{/* (ind),y */\ 91 {\
701 fuint16 temp = READ_LOW( data ) + y;\ 92 out [addr] = data;\
702 PAGE_CROSS_PENALTY( temp );\
703 data = temp + 0x100 * READ_LOW( (uint8_t) (data + 1) );\
704 goto ptr##op;\
705 }\ 93 }\
706 case op + 0x10: /* zp,X */\ 94 else if ( cpu->mmr [page] == 0xFF )\
707 data = (uint8_t) (data + x);\ 95 {\
708 case op + 0x00: /* zp */\
709 data = READ_LOW( data );\
710 goto imm##op;\
711 case op + 0x14: /* abs,Y */\
712 data += y;\
713 goto ind##op;\
714 case op + 0x18: /* abs,X */\
715 data += x;\
716 ind##op:\
717 PAGE_CROSS_PENALTY( data );\
718 case op + 0x08: /* abs */\
719 ADD_PAGE( data );\
720 ptr##op:\
721 FLUSH_TIME();\ 96 FLUSH_TIME();\
722 data = READ( data );\ 97 write_mem_( this, addr, data );\
723 CACHE_TIME();\ 98 CACHE_TIME();\
724 case op + 0x04: /* imm */\ 99 }\
725 imm##op: 100}
726
727 ARITH_ADDR_MODES( 0xC5 ) // CMP
728 nz = a - data;
729 pc++;
730 c = ~nz;
731 nz &= 0xFF;
732 goto loop;
733
734 ARITH_ADDR_MODES( 0x25 ) // AND
735 nz = (a &= data);
736 pc++;
737 goto loop;
738
739 ARITH_ADDR_MODES( 0x45 ) // EOR
740 nz = (a ^= data);
741 pc++;
742 goto loop;
743
744 ARITH_ADDR_MODES( 0x05 ) // ORA
745 nz = (a |= data);
746 pc++;
747 goto loop;
748
749// Add/subtract
750
751 ARITH_ADDR_MODES( 0xE5 ) // SBC
752 data ^= 0xFF;
753 goto adc_imm;
754
755 ARITH_ADDR_MODES( 0x65 ) // ADC
756 adc_imm: {
757 if ( status & st_d ) {
758 dprintf( "Decimal mode not supported\n" );
759 }
760 fint16 carry = c >> 8 & 1;
761 fint16 ov = (a ^ 0x80) + carry + (int8_t) data; // sign-extend
762 status &= ~st_v;
763 status |= ov >> 2 & 0x40;
764 c = nz = a + data + carry;
765 pc++;
766 a = (uint8_t) nz;
767 goto loop;
768 }
769
770// Shift/rotate
771
772 case 0x4A: // LSR A
773 c = 0;
774 case 0x6A: // ROR A
775 nz = c >> 1 & 0x80;
776 c = a << 8;
777 nz |= a >> 1;
778 a = nz;
779 goto loop;
780
781 case 0x0A: // ASL A
782 nz = a << 1;
783 c = nz;
784 a = (uint8_t) nz;
785 goto loop;
786
787 case 0x2A: { // ROL A
788 nz = a << 1;
789 fint16 temp = c >> 8 & 1;
790 c = nz;
791 nz |= temp;
792 a = (uint8_t) nz;
793 goto loop;
794 }
795
796 case 0x5E: // LSR abs,X
797 data += x;
798 case 0x4E: // LSR abs
799 c = 0;
800 case 0x6E: // ROR abs
801 ror_abs: {
802 ADD_PAGE( data );
803 FLUSH_TIME();
804 int temp = READ( data );
805 nz = (c >> 1 & 0x80) | (temp >> 1);
806 c = temp << 8;
807 goto rotate_common;
808 }
809
810 case 0x3E: // ROL abs,X
811 data += x;
812 goto rol_abs;
813
814 case 0x1E: // ASL abs,X
815 data += x;
816 case 0x0E: // ASL abs
817 c = 0;
818 case 0x2E: // ROL abs
819 rol_abs:
820 ADD_PAGE( data );
821 nz = c >> 8 & 1;
822 FLUSH_TIME();
823 nz |= (c = READ( data ) << 1);
824 rotate_common:
825 pc++;
826 WRITE( data, (uint8_t) nz );
827 CACHE_TIME();
828 goto loop;
829
830 case 0x7E: // ROR abs,X
831 data += x;
832 goto ror_abs;
833
834 case 0x76: // ROR zp,x
835 data = (uint8_t) (data + x);
836 goto ror_zp;
837
838 case 0x56: // LSR zp,x
839 data = (uint8_t) (data + x);
840 case 0x46: // LSR zp
841 c = 0;
842 case 0x66: // ROR zp
843 ror_zp: {
844 int temp = READ_LOW( data );
845 nz = (c >> 1 & 0x80) | (temp >> 1);
846 c = temp << 8;
847 goto write_nz_zp;
848 }
849
850 case 0x36: // ROL zp,x
851 data = (uint8_t) (data + x);
852 goto rol_zp;
853
854 case 0x16: // ASL zp,x
855 data = (uint8_t) (data + x);
856 case 0x06: // ASL zp
857 c = 0;
858 case 0x26: // ROL zp
859 rol_zp:
860 nz = c >> 8 & 1;
861 nz |= (c = READ_LOW( data ) << 1);
862 goto write_nz_zp;
863
864// Increment/decrement
865
866#define INC_DEC_AXY( reg, n ) reg = (uint8_t) (nz = reg + n); goto loop;
867
868 case 0x1A: // INA
869 INC_DEC_AXY( a, +1 )
870
871 case 0xE8: // INX
872 INC_DEC_AXY( x, +1 )
873
874 case 0xC8: // INY
875 INC_DEC_AXY( y, +1 )
876
877 case 0x3A: // DEA
878 INC_DEC_AXY( a, -1 )
879
880 case 0xCA: // DEX
881 INC_DEC_AXY( x, -1 )
882
883 case 0x88: // DEY
884 INC_DEC_AXY( y, -1 )
885
886 case 0xF6: // INC zp,x
887 data = (uint8_t) (data + x);
888 case 0xE6: // INC zp
889 nz = 1;
890 goto add_nz_zp;
891
892 case 0xD6: // DEC zp,x
893 data = (uint8_t) (data + x);
894 case 0xC6: // DEC zp
895 nz = (unsigned) -1;
896 add_nz_zp:
897 nz += READ_LOW( data );
898 write_nz_zp:
899 pc++;
900 WRITE_LOW( data, nz );
901 goto loop;
902
903 case 0xFE: // INC abs,x
904 data = x + GET_ADDR();
905 goto inc_ptr;
906
907 case 0xEE: // INC abs
908 data = GET_ADDR();
909 inc_ptr:
910 nz = 1;
911 goto inc_common;
912
913 case 0xDE: // DEC abs,x
914 data = x + GET_ADDR();
915 goto dec_ptr;
916
917 case 0xCE: // DEC abs
918 data = GET_ADDR();
919 dec_ptr:
920 nz = (unsigned) -1;
921 inc_common:
922 FLUSH_TIME();
923 nz += READ( data );
924 pc += 2;
925 WRITE( data, (uint8_t) nz );
926 CACHE_TIME();
927 goto loop;
928
929// Transfer
930
931 case 0xA8: // TAY
932 y = a;
933 nz = a;
934 goto loop;
935
936 case 0x98: // TYA
937 a = y;
938 nz = y;
939 goto loop;
940
941 case 0xAA: // TAX
942 x = a;
943 nz = a;
944 goto loop;
945
946 case 0x8A: // TXA
947 a = x;
948 nz = x;
949 goto loop;
950
951 case 0x9A: // TXS
952 SET_SP( x ); // verified (no flag change)
953 goto loop;
954
955 case 0xBA: // TSX
956 x = nz = GET_SP();
957 goto loop;
958
959 #define SWAP_REGS( r1, r2 ) {\
960 fuint8 t = r1;\
961 r1 = r2;\
962 r2 = t;\
963 goto loop;\
964 }
965
966 case 0x02: // SXY
967 SWAP_REGS( x, y );
968
969 case 0x22: // SAX
970 SWAP_REGS( a, x );
971
972 case 0x42: // SAY
973 SWAP_REGS( a, y );
974
975 case 0x62: // CLA
976 a = 0;
977 goto loop;
978
979 case 0x82: // CLX
980 x = 0;
981 goto loop;
982
983 case 0xC2: // CLY
984 y = 0;
985 goto loop;
986
987// Stack
988
989 case 0x48: // PHA
990 PUSH( a );
991 goto loop;
992
993 case 0xDA: // PHX
994 PUSH( x );
995 goto loop;
996
997 case 0x5A: // PHY
998 PUSH( y );
999 goto loop;
1000
1001 case 0x40:{// RTI
1002 fuint8 temp = READ_LOW( sp );
1003 pc = READ_LOW( 0x100 | (sp - 0xFF) );
1004 pc |= READ_LOW( 0x100 | (sp - 0xFE) ) * 0x100;
1005 sp = (sp - 0xFD) | 0x100;
1006 data = status;
1007 SET_STATUS( temp );
1008 r->status = status; // update externally-visible I flag
1009 if ( (data ^ status) & st_i )
1010 {
1011 hes_time_t new_time = cpu->end_time;
1012 if ( !(status & st_i) && new_time > cpu->irq_time )
1013 new_time = cpu->irq_time;
1014 blargg_long delta = s.base - new_time;
1015 s.base = new_time;
1016 s_time += delta;
1017 }
1018 goto loop;
1019 }
1020
1021 #define POP() READ_LOW( sp ); sp = (sp - 0xFF) | 0x100
1022
1023 case 0x68: // PLA
1024 a = nz = POP();
1025 goto loop;
1026
1027 case 0xFA: // PLX
1028 x = nz = POP();
1029 goto loop;
1030
1031 case 0x7A: // PLY
1032 y = nz = POP();
1033 goto loop;
1034
1035 case 0x28:{// PLP
1036 fuint8 temp = POP();
1037 fuint8 changed = status ^ temp;
1038 SET_STATUS( temp );
1039 if ( !(changed & st_i) )
1040 goto loop; // I flag didn't change
1041 if ( status & st_i )
1042 goto handle_sei;
1043 goto handle_cli;
1044 }
1045 #undef POP
1046
1047 case 0x08: { // PHP
1048 fuint8 temp;
1049 CALC_STATUS( temp );
1050 PUSH( temp | st_b );
1051 goto loop;
1052 }
1053
1054// Flags
1055
1056 case 0x38: // SEC
1057 c = (unsigned) ~0;
1058 goto loop;
1059
1060 case 0x18: // CLC
1061 c = 0;
1062 goto loop;
1063
1064 case 0xB8: // CLV
1065 status &= ~st_v;
1066 goto loop;
1067
1068 case 0xD8: // CLD
1069 status &= ~st_d;
1070 goto loop;
1071
1072 case 0xF8: // SED
1073 status |= st_d;
1074 goto loop;
1075
1076 case 0x58: // CLI
1077 if ( !(status & st_i) )
1078 goto loop;
1079 status &= ~st_i;
1080 handle_cli: {
1081 r->status = status; // update externally-visible I flag
1082 blargg_long delta = s.base - cpu->irq_time;
1083 if ( delta <= 0 )
1084 {
1085 if ( TIME < cpu->irq_time )
1086 goto loop;
1087 goto delayed_cli;
1088 }
1089 s.base = cpu->irq_time;
1090 s_time += delta;
1091 if ( s_time < 0 )
1092 goto loop;
1093
1094 if ( delta >= s_time + 1 )
1095 {
1096 // delayed irq until after next instruction
1097 s.base += s_time + 1;
1098 s_time = -1;
1099 cpu->irq_time = s.base; // TODO: remove, as only to satisfy debug check in loop
1100 goto loop;
1101 }
1102 delayed_cli:
1103 dprintf( "Delayed CLI not supported\n" ); // TODO: implement
1104 goto loop;
1105 }
1106
1107 case 0x78: // SEI
1108 if ( status & st_i )
1109 goto loop;
1110 status |= st_i;
1111 handle_sei: {
1112 r->status = status; // update externally-visible I flag
1113 blargg_long delta = s.base - cpu->end_time;
1114 s.base = cpu->end_time;
1115 s_time += delta;
1116 if ( s_time < 0 )
1117 goto loop;
1118 dprintf( "Delayed SEI not supported\n" ); // TODO: implement
1119 goto loop;
1120 }
1121
1122// Special
1123
1124 case 0x53:{// TAM
1125 fuint8 const bits = data; // avoid using data across function call
1126 pc++;
1127 int i;
1128 for ( i = 0; i < 8; i++ )
1129 if ( bits & (1 << i) )
1130 /* this->cpu.set_mmr( i, a ); */
1131 Cpu_set_mmr( this, i, a );
1132 goto loop;
1133 }
1134
1135 case 0x43:{// TMA
1136 pc++;
1137 byte const* in = cpu->mmr;
1138 do
1139 {
1140 if ( data & 1 )
1141 a = *in;
1142 in++;
1143 }
1144 while ( (data >>= 1) != 0 );
1145 goto loop;
1146 }
1147
1148 case 0x03: // ST0
1149 case 0x13: // ST1
1150 case 0x23:{// ST2
1151 fuint16 addr = opcode >> 4;
1152 if ( addr )
1153 addr++;
1154 pc++;
1155 FLUSH_TIME();
1156 CPU_WRITE_VDP( this, addr, data, TIME );
1157 CACHE_TIME();
1158 goto loop;
1159 }
1160
1161 case 0xEA: // NOP
1162 goto loop;
1163
1164 case 0x54: // CSL
1165 dprintf( "CSL not supported\n" );
1166 illegal_encountered = true;
1167 goto loop;
1168
1169 case 0xD4: // CSH
1170 goto loop;
1171
1172 case 0xF4: { // SET
1173 //fuint16 operand = GET_MSB();
1174 dprintf( "SET not handled\n" );
1175 //switch ( data )
1176 //{
1177 //}
1178 illegal_encountered = true;
1179 goto loop;
1180 }
1181
1182// Block transfer
1183 101
1184 { 102#define READ_LOW( addr ) (this->ram [addr])
1185 fuint16 in_alt; 103#define WRITE_LOW( addr, data ) (this->ram [addr] = data)
1186 fint16 in_inc; 104#define READ_MEM( addr ) read_mem( this, addr )
1187 fuint16 out_alt; 105#define WRITE_MEM( addr, data ) write_mem( this, addr, data )
1188 fint16 out_inc; 106#define WRITE_VDP( addr, data ) write_vdp( this, addr, data )
1189 107#define CPU_DONE( result_out ) { FLUSH_TIME(); result_out = cpu_done( this ); CACHE_TIME(); }
1190 case 0xE3: // TIA 108#define SET_MMR( reg, bank ) set_mmr( this, reg, bank )
1191 in_alt = 0;
1192 goto bxfer_alt;
1193
1194 case 0xF3: // TAI
1195 in_alt = 1;
1196 bxfer_alt:
1197 in_inc = in_alt ^ 1;
1198 out_alt = in_inc;
1199 out_inc = in_alt;
1200 goto bxfer;
1201
1202 case 0xD3: // TIN
1203 in_inc = 1;
1204 out_inc = 0;
1205 goto bxfer_no_alt;
1206
1207 case 0xC3: // TDD
1208 in_inc = -1;
1209 out_inc = -1;
1210 goto bxfer_no_alt;
1211
1212 case 0x73: // TII
1213 in_inc = 1;
1214 out_inc = 1;
1215 bxfer_no_alt:
1216 in_alt = 0;
1217 out_alt = 0;
1218 bxfer: {
1219 fuint16 in = GET_LE16( instr + 0 );
1220 fuint16 out = GET_LE16( instr + 2 );
1221 int count = GET_LE16( instr + 4 );
1222 if ( !count )
1223 count = 0x10000;
1224 pc += 6;
1225 WRITE_LOW( 0x100 | (sp - 1), y );
1226 WRITE_LOW( 0x100 | (sp - 2), a );
1227 WRITE_LOW( 0x100 | (sp - 3), x );
1228 FLUSH_TIME();
1229 do
1230 {
1231 // TODO: reads from $0800-$1400 in I/O page return 0 and don't access I/O
1232 fuint8 t = READ( in );
1233 in += in_inc;
1234 in &= 0xFFFF;
1235 s.time += 6;
1236 if ( in_alt )
1237 in_inc = -in_inc;
1238 WRITE( out, t );
1239 out += out_inc;
1240 out &= 0xFFFF;
1241 if ( out_alt )
1242 out_inc = -out_inc;
1243 }
1244 while ( --count );
1245 CACHE_TIME();
1246 goto loop;
1247 }
1248 }
1249 109
1250// Illegal 110#define IDLE_ADDR idle_addr
1251 111
1252 default: 112#define CPU_BEGIN \
1253 assert( (unsigned) opcode <= 0xFF ); 113bool run_cpu( struct Hes_Emu* this, hes_time_t end_time )\
1254 dprintf( "Illegal opcode $%02X at $%04X\n", (int) opcode, (int) pc - 1 ); 114{\
1255 illegal_encountered = true; 115 struct Hes_Cpu* cpu = &this->cpu;\
1256 goto loop; 116 Cpu_set_end_time( cpu, end_time );
1257 }
1258 assert( false );
1259
1260 int result_;
1261handle_brk:
1262 pc++;
1263 result_ = 6;
1264
1265interrupt:
1266 {
1267 s_time += 7;
1268
1269 WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
1270 WRITE_LOW( 0x100 | (sp - 2), pc );
1271 pc = GET_LE16( &READ_PROG( 0xFFF0 ) + result_ );
1272
1273 sp = (sp - 3) | 0x100;
1274 fuint8 temp;
1275 CALC_STATUS( temp );
1276 if ( result_ == 6 )
1277 temp |= st_b;
1278 WRITE_LOW( sp, temp );
1279
1280 status &= ~st_d;
1281 status |= st_i;
1282 r->status = status; // update externally-visible I flag
1283
1284 blargg_long delta = s.base - cpu->end_time;
1285 s.base = cpu->end_time;
1286 s_time += delta;
1287 goto loop;
1288 }
1289
1290idle_done:
1291 s_time = 0;
1292out_of_time:
1293 pc--;
1294 FLUSH_TIME();
1295 CPU_DONE( this, TIME, result_ );
1296 CACHE_TIME();
1297 if ( result_ > 0 )
1298 goto interrupt;
1299 if ( s_time < 0 )
1300 goto loop;
1301
1302 s.time = s_time;
1303
1304 r->pc = pc;
1305 r->sp = GET_SP();
1306 r->a = a;
1307 r->x = x;
1308 r->y = y;
1309
1310 {
1311 fuint8 temp;
1312 CALC_STATUS( temp );
1313 r->status = temp;
1314 }
1315 117
1316 cpu->state_ = s; 118 #include "hes_cpu_run.h"
1317 cpu->state = &cpu->state_;
1318 119
1319 return illegal_encountered; 120 return illegal_encountered;
1320} 121}
1321
diff --git a/apps/codecs/libgme/hes_cpu.h b/apps/codecs/libgme/hes_cpu.h
index 4d76c83a3b..0429eeaba0 100644
--- a/apps/codecs/libgme/hes_cpu.h
+++ b/apps/codecs/libgme/hes_cpu.h
@@ -1,56 +1,52 @@
1// PC Engine CPU emulator for use with HES music files 1// PC Engine CPU emulator for use with HES music files
2 2
3// Game_Music_Emu 0.5.2 3// Game_Music_Emu 0.6-pre
4#ifndef HES_CPU_H 4#ifndef HES_CPU_H
5#define HES_CPU_H 5#define HES_CPU_H
6 6
7#include "blargg_common.h" 7#include "blargg_common.h"
8#include "blargg_source.h"
8 9
9typedef blargg_long hes_time_t; // clock cycle count 10typedef int hes_time_t; // clock cycle count
10typedef unsigned hes_addr_t; // 16-bit address 11typedef int hes_addr_t; // 16-bit address
11 12
12struct Hes_Emu; 13struct Hes_Emu;
13 14
14enum { future_hes_time = LONG_MAX / 2 + 1 }; 15enum { future_time = INT_MAX/2 + 1 };
15enum { page_size = 0x2000 }; 16enum { page_bits = 13 };
16enum { page_shift = 13 }; 17enum { page_size = 1 << page_bits };
17enum { page_count = 8 }; 18enum { page_count = 0x10000 / page_size };
18 19
19// Attempt to execute instruction here results in CPU advancing time to
20// lesser of irq_time() and end_time() (or end_time() if IRQs are
21// disabled)
22enum { idle_addr = 0x1FFF };
23
24// Can read this many bytes past end of a page 20// Can read this many bytes past end of a page
25enum { cpu_padding = 8 }; 21enum { cpu_padding = 8 };
26enum { irq_inhibit = 0x04 }; 22enum { irq_inhibit_mask = 0x04 };
27 23enum { idle_addr = 0x1FFF };
28 24
29// Cpu state 25// Cpu state
30struct state_t { 26struct cpu_state_t {
31 uint8_t const* code_map [page_count + 1]; 27 byte const* code_map [page_count + 1];
32 hes_time_t base; 28 hes_time_t base;
33 blargg_long time; 29 int time;
34}; 30};
35 31
36// Cpu registers 32// NOT kept updated during emulation.
37struct registers_t { 33struct registers_t {
38 uint16_t pc; 34 uint16_t pc;
39 uint8_t a; 35 byte a;
40 uint8_t x; 36 byte x;
41 uint8_t y; 37 byte y;
42 uint8_t status; 38 byte flags;
43 uint8_t sp; 39 byte sp;
44}; 40};
45 41
46struct Hes_Cpu { 42struct Hes_Cpu {
47 struct registers_t r; 43 struct registers_t r;
48 44
49 hes_time_t irq_time; 45 hes_time_t irq_time_;
50 hes_time_t end_time; 46 hes_time_t end_time_;
51 47
52 struct state_t* state; // points to state_ or a local copy within run() 48 struct cpu_state_t* cpu_state; // points to state_ or a local copy within run()
53 struct state_t state_; 49 struct cpu_state_t cpu_state_;
54 50
55 // page mapping registers 51 // page mapping registers
56 uint8_t mmr [page_count + 1]; 52 uint8_t mmr [page_count + 1];
@@ -58,7 +54,10 @@ struct Hes_Cpu {
58}; 54};
59 55
60// Init cpu state 56// Init cpu state
61void Cpu_init( struct Hes_Cpu* this ); 57static inline void Cpu_init( struct Hes_Cpu* this )
58{
59 this->cpu_state = &this->cpu_state_;
60}
62 61
63// Reset hes cpu 62// Reset hes cpu
64void Cpu_reset( struct Hes_Cpu* this ); 63void Cpu_reset( struct Hes_Cpu* this );
@@ -67,29 +66,67 @@ void Cpu_reset( struct Hes_Cpu* this );
67// instructions were encountered. 66// instructions were encountered.
68bool Cpu_run( struct Hes_Emu* this, hes_time_t end_time ); 67bool Cpu_run( struct Hes_Emu* this, hes_time_t end_time );
69 68
70void Cpu_set_mmr( struct Hes_Emu* this, int reg, int bank );
71
72// Time of ning of next instruction to be executed 69// Time of ning of next instruction to be executed
73static inline hes_time_t Cpu_time( struct Hes_Cpu* this ) 70static inline hes_time_t Cpu_time( struct Hes_Cpu* this )
74{ 71{
75 return this->state->time + this->state->base; 72 return this->cpu_state->time + this->cpu_state->base;
76} 73}
77 74
75static inline void Cpu_set_time( struct Hes_Cpu* this, hes_time_t t ) { this->cpu_state->time = t - this->cpu_state->base; }
76static inline void Cpu_adjust_time( struct Hes_Cpu* this, int delta ) { this->cpu_state->time += delta; }
77
78#define HES_CPU_PAGE( addr ) ((unsigned) (addr) >> page_bits)
79
80#ifdef BLARGG_NONPORTABLE
81 #define HES_CPU_OFFSET( addr ) (addr)
82#else
83 #define HES_CPU_OFFSET( addr ) ((addr) & (page_size - 1))
84#endif
85
78static inline uint8_t const* Cpu_get_code( struct Hes_Cpu* this, hes_addr_t addr ) 86static inline uint8_t const* Cpu_get_code( struct Hes_Cpu* this, hes_addr_t addr )
79{ 87{
80 return this->state->code_map [addr >> page_shift] + addr 88 return this->cpu_state_.code_map [HES_CPU_PAGE( addr )] + HES_CPU_OFFSET( addr );
81 #if !defined (BLARGG_NONPORTABLE) 89}
82 % (unsigned) page_size 90
83 #endif 91static inline void update_end_time( struct Hes_Cpu* this, hes_time_t end, hes_time_t irq )
84 ; 92{
93 if ( end > irq && !(this->r.flags & irq_inhibit_mask) )
94 end = irq;
95
96 this->cpu_state->time += this->cpu_state->base - end;
97 this->cpu_state->base = end;
98}
99
100static inline hes_time_t Cpu_end_time( struct Hes_Cpu* this ) { return this->end_time_; }
101
102static inline void Cpu_set_irq_time( struct Hes_Cpu* this, hes_time_t t )
103{
104 this->irq_time_ = t;
105 update_end_time( this, this->end_time_, t );
106}
107
108static inline void Cpu_set_end_time( struct Hes_Cpu* this, hes_time_t t )
109{
110 this->end_time_ = t;
111 update_end_time( this, t, this->irq_time_ );
112}
113
114static inline void Cpu_end_frame( struct Hes_Cpu* this, hes_time_t t )
115{
116 assert( this->cpu_state == &this->cpu_state_ );
117 this->cpu_state_.base -= t;
118 if ( this->irq_time_ < future_time ) this->irq_time_ -= t;
119 if ( this->end_time_ < future_time ) this->end_time_ -= t;
85} 120}
86 121
87static inline int Cpu_update_end_time( struct Hes_Cpu* this, uint8_t reg_status, hes_time_t t, hes_time_t irq ) 122static inline void Cpu_set_mmr( struct Hes_Cpu* this, int reg, int bank, void const* code )
88{ 123{
89 if ( irq < t && !(reg_status & irq_inhibit) ) t = irq; 124 assert( (unsigned) reg <= page_count ); // allow page past end to be set
90 int delta = this->state->base - t; 125 assert( (unsigned) bank < 0x100 );
91 this->state->base = t; 126 this->mmr [reg] = bank;
92 return delta; 127 byte const* p = STATIC_CAST(byte const*,code) - HES_CPU_OFFSET( reg << page_bits );
128 this->cpu_state->code_map [reg] = p;
129 this->cpu_state_.code_map [reg] = p;
93} 130}
94 131
95#endif 132#endif
diff --git a/apps/codecs/libgme/hes_cpu_io.h b/apps/codecs/libgme/hes_cpu_io.h
deleted file mode 100644
index 6b49c69e22..0000000000
--- a/apps/codecs/libgme/hes_cpu_io.h
+++ /dev/null
@@ -1,72 +0,0 @@
1
2#include "hes_emu.h"
3
4#include "blargg_source.h"
5
6int Cpu_read( struct Hes_Emu* this, hes_addr_t addr )
7{
8 check( addr <= 0xFFFF );
9 int result = *Cpu_get_code( &this->cpu, addr );
10 if ( this->cpu.mmr [addr >> page_shift] == 0xFF )
11 result = Emu_cpu_read( this, addr );
12 return result;
13}
14
15void Cpu_write( struct Hes_Emu* this, hes_addr_t addr, int data )
16{
17 check( addr <= 0xFFFF );
18 byte* out = this->write_pages [addr >> page_shift];
19 addr &= page_size - 1;
20 if ( out )
21 out [addr] = data;
22 else if ( this->cpu.mmr [addr >> page_shift] == 0xFF )
23 Emu_cpu_write( this, addr, data );
24}
25
26#define CPU_READ_FAST( emu, addr, time, out ) \
27 CPU_READ_FAST_( emu, addr, time, out )
28
29#define CPU_READ_FAST_( emu, addr, time, out ) \
30{\
31 out = READ_PROG( addr );\
32 if ( emu->cpu.mmr [addr >> page_shift] == 0xFF )\
33 {\
34 FLUSH_TIME();\
35 out = Emu_cpu_read( emu, addr );\
36 CACHE_TIME();\
37 }\
38}
39
40#define CPU_WRITE_FAST( emu, addr, data, time ) \
41 CPU_WRITE_FAST_( emu, addr, data, time )
42
43#define CPU_WRITE_FAST_( emu, addr, data, time ) \
44{\
45 byte* out = emu->write_pages [addr >> page_shift];\
46 addr &= page_size - 1;\
47 if ( out )\
48 {\
49 out [addr] = data;\
50 }\
51 else if ( emu->cpu.mmr [addr >> page_shift] == 0xFF )\
52 {\
53 FLUSH_TIME();\
54 Emu_cpu_write( emu, addr, data );\
55 CACHE_TIME();\
56 }\
57}
58
59#define CPU_READ( emu, addr, time ) \
60 Cpu_read( emu, addr )
61
62#define CPU_WRITE( emu, addr, data, time ) \
63 Cpu_write( emu, addr, data )
64
65#define CPU_WRITE_VDP( emu, addr, data, time ) \
66 Cpu_write_vdp( emu, addr, data )
67
68#define CPU_SET_MMR( emu, page, bank ) \
69 Emu_cpu_set_mmr( emu, page, bank )
70
71#define CPU_DONE( emu, time, result_out ) \
72 result_out = Cpu_done( emu )
diff --git a/apps/codecs/libgme/hes_cpu_run.h b/apps/codecs/libgme/hes_cpu_run.h
new file mode 100644
index 0000000000..bfba2b6109
--- /dev/null
+++ b/apps/codecs/libgme/hes_cpu_run.h
@@ -0,0 +1,1344 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#if 0
4/* Define these macros in the source file before #including this file.
5- Parameters might be expressions, so they are best evaluated only once,
6though they NEVER have side-effects, so multiple evaluation is OK.
7- Output parameters might be a multiple-assignment expression like "a=x",
8so they must NOT be parenthesized.
9- Except where noted, time() and related functions will NOT work
10correctly inside a macro. TIME() is always correct, and FLUSH_TIME() and
11CACHE_TIME() allow the time changing functions to work.
12- Macros "returning" void may use a {} statement block. */
13
14 // 0 <= addr <= 0xFFFF + page_size
15 // time functions can be used
16 int READ_MEM( addr_t );
17 void WRITE_MEM( addr_t, int data );
18
19 // 0 <= addr <= 0x1FF
20 int READ_LOW( addr_t );
21 void WRITE_LOW( addr_t, int data );
22
23 // 0 <= addr <= 0xFFFF + page_size
24 // Used by common instructions.
25 int READ_FAST( addr_t, int& out );
26 void WRITE_FAST( addr_t, int data );
27
28 // 0 <= addr <= 2
29 // ST0, ST1, ST2 instructions
30 void WRITE_VDP( int addr, int data );
31
32// The following can be used within macros:
33
34 // Current time
35 hes_time_t TIME();
36
37 // Allows use of time functions
38 void FLUSH_TIME();
39
40 // Must be used before end of macro if FLUSH_TIME() was used earlier
41 void CACHE_TIME();
42
43// Configuration (optional; commented behavior if defined)
44
45 // Expanded just before beginning of code, to help debugger
46 #define CPU_BEGIN void my_run_cpu() {
47#endif
48
49/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
50can redistribute it and/or modify it under the terms of the GNU Lesser
51General Public License as published by the Free Software Foundation; either
52version 2.1 of the License, or (at your option) any later version. This
53module is distributed in the hope that it will be useful, but WITHOUT ANY
54WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
55FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
56details. You should have received a copy of the GNU Lesser General Public
57License along with this module; if not, write to the Free Software Foundation,
58Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
59
60// TODO: support T flag, including clearing it at appropriate times?
61
62// all zero-page should really use whatever is at page 1, but that would
63// reduce efficiency quite a bit
64int const ram_addr = 0x2000;
65
66void Cpu_reset( struct Hes_Cpu* this )
67{
68 check( this->cpu_state == &this->cpu_state_ );
69 this->cpu_state = &this->cpu_state_;
70
71 this->cpu_state_.time = 0;
72 this->cpu_state_.base = 0;
73 this->irq_time_ = future_time;
74 this->end_time_ = future_time;
75
76 this->r.flags = 0x04;
77 this->r.sp = 0;
78 this->r.pc = 0;
79 this->r.a = 0;
80 this->r.x = 0;
81 this->r.y = 0;
82
83 // Be sure "blargg_endian.h" has been #included
84 blargg_verify_byte_order();
85}
86
87// Allows MWCW debugger to step through code properly
88#ifdef CPU_BEGIN
89 CPU_BEGIN
90#endif
91
92// Time
93#define TIME() (s_time + s.base)
94#define FLUSH_TIME() {s.time = s_time;}
95#define CACHE_TIME() {s_time = s.time;}
96
97// Memory
98#define READ_STACK READ_LOW
99#define WRITE_STACK WRITE_LOW
100
101#define CODE_PAGE( addr ) s.code_map [HES_CPU_PAGE( addr )]
102#define CODE_OFFSET( addr ) HES_CPU_OFFSET( addr )
103#define READ_CODE( addr ) CODE_PAGE( addr ) [CODE_OFFSET( addr )]
104
105// Stack
106#define SET_SP( v ) (sp = ((v) + 1) | 0x100)
107#define GET_SP() ((sp - 1) & 0xFF)
108#define SP( o ) ((sp + (o - (o>0)*0x100)) | 0x100)
109
110// Truncation
111#define BYTE( n ) ((uint8_t ) (n)) /* (unsigned) n & 0xFF */
112#define SBYTE( n ) ((int8_t ) (n)) /* (BYTE( n ) ^ 0x80) - 0x80 */
113#define WORD( n ) ((uint16_t) (n)) /* (unsigned) n & 0xFFFF */
114
115// Flags with hex value for clarity when used as mask.
116// Stored in indicated variable during emulation.
117int const n80 = 0x80; // nz
118int const v40 = 0x40; // flags
119//int const t20 = 0x20;
120int const b10 = 0x10;
121int const d08 = 0x08; // flags
122int const i04 = 0x04; // flags
123int const z02 = 0x02; // nz
124int const c01 = 0x01; // c
125
126#define IS_NEG (nz & 0x8080)
127
128#define GET_FLAGS( out ) \
129{\
130 out = flags & (v40 | d08 | i04);\
131 out += ((nz >> 8) | nz) & n80;\
132 out += c >> 8 & c01;\
133 if ( !BYTE( nz ) )\
134 out += z02;\
135}
136
137#define SET_FLAGS( in ) \
138{\
139 flags = in & (v40 | d08 | i04);\
140 c = nz = in << 8;\
141 nz += ~in & z02;\
142}
143
144bool illegal_encountered = false;
145{
146 struct cpu_state_t s = cpu->cpu_state_;
147 cpu->cpu_state = &s;
148 // even on x86, using s.time in place of s_time was slower
149 int s_time = s.time;
150
151 // registers
152 int pc = cpu->r.pc;
153 int a = cpu->r.a;
154 int x = cpu->r.x;
155 int y = cpu->r.y;
156 int sp;
157 SET_SP( cpu->r.sp );
158
159 // Flags
160 int flags;
161 int c; // carry set if (c & 0x100) != 0
162 int nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
163 {
164 int temp = cpu->r.flags;
165 SET_FLAGS( temp );
166 }
167
168loop:
169
170 #ifndef NDEBUG
171 {
172 hes_time_t correct = cpu->end_time_;
173 if ( !(flags & i04) && correct > cpu->irq_time_ )
174 correct = cpu->irq_time_;
175 check( s.base == correct );
176 /*
177 static int count;
178 if ( count == 1844 ) Debugger();
179 if ( s.base != correct ) dprintf( "%ld\n", count );
180 count++;
181 */
182 }
183 #endif
184
185 // Check all values
186 check( (unsigned) sp - 0x100 < 0x100 );
187 check( (unsigned) pc < 0x10000 + 0x100 ); // +0x100 so emulator can catch wrap-around
188 check( (unsigned) a < 0x100 );
189 check( (unsigned) x < 0x100 );
190 check( (unsigned) y < 0x100 );
191
192 // Read instruction
193 byte const* instr = CODE_PAGE( pc );
194 int opcode;
195
196 if ( CODE_OFFSET(~0) == ~0 )
197 {
198 opcode = instr [pc];
199 pc++;
200 instr += pc;
201 }
202 else
203 {
204 instr += CODE_OFFSET( pc );
205 opcode = *instr++;
206 pc++;
207 }
208
209 // TODO: each reference lists slightly different timing values, ugh
210 static byte const clock_table [256] =
211 {// 0 1 2 3 4 5 6 7 8 9 A B C D E F
212 1,7,3, 4,6,4,6,7,3,2,2,2,7,5,7,4,// 0
213 2,7,7, 4,6,4,6,7,2,5,2,2,7,5,7,4,// 1
214 7,7,3, 4,4,4,6,7,4,2,2,2,5,5,7,4,// 2
215 2,7,7, 2,4,4,6,7,2,5,2,2,5,5,7,4,// 3
216 7,7,3, 4,8,4,6,7,3,2,2,2,4,5,7,4,// 4
217 2,7,7, 5,2,4,6,7,2,5,3,2,2,5,7,4,// 5
218 7,7,2, 2,4,4,6,7,4,2,2,2,7,5,7,4,// 6
219 2,7,7,17,4,4,6,7,2,5,4,2,7,5,7,4,// 7
220 4,7,2, 7,4,4,4,7,2,2,2,2,5,5,5,4,// 8
221 2,7,7, 8,4,4,4,7,2,5,2,2,5,5,5,4,// 9
222 2,7,2, 7,4,4,4,7,2,2,2,2,5,5,5,4,// A
223 2,7,7, 8,4,4,4,7,2,5,2,2,5,5,5,4,// B
224 2,7,2,17,4,4,6,7,2,2,2,2,5,5,7,4,// C
225 2,7,7,17,2,4,6,7,2,5,3,2,2,5,7,4,// D
226 2,7,2,17,4,4,6,7,2,2,2,2,5,5,7,4,// E
227 2,7,7,17,2,4,6,7,2,5,4,2,2,5,7,4 // F
228 }; // 0x00 was 8
229
230 // Update time
231 if ( s_time >= 0 )
232 goto out_of_time;
233
234 #ifdef HES_CPU_LOG_H
235 log_cpu( "new", pc - 1, opcode, instr [0], instr [1], instr [2],
236 instr [3], instr [4], instr [5], a, x, y );
237 //log_opcode( opcode );
238 #endif
239
240 s_time += clock_table [opcode];
241
242 int data;
243 data = *instr;
244
245 switch ( opcode )
246 {
247// Macros
248
249#define GET_MSB() (instr [1])
250#define ADD_PAGE( out ) (pc++, out = data + 0x100 * GET_MSB());
251#define GET_ADDR() GET_LE16( instr )
252
253// TODO: is the penalty really always added? the original 6502 was much better
254//#define PAGE_PENALTY( lsb ) (void) (s_time += (lsb) >> 8)
255#define PAGE_PENALTY( lsb )
256
257// Branch
258
259// TODO: more efficient way to handle negative branch that wraps PC around
260#define BRANCH_( cond, adj )\
261{\
262 pc++;\
263 if ( !(cond) ) goto loop;\
264 pc = (uint16_t) (pc + SBYTE( data ));\
265 s_time += adj;\
266 goto loop;\
267}
268
269#define BRANCH( cond ) BRANCH_( cond, 2 )
270
271 case 0xF0: // BEQ
272 BRANCH( !BYTE( nz ) );
273
274 case 0xD0: // BNE
275 BRANCH( BYTE( nz ) );
276
277 case 0x10: // BPL
278 BRANCH( !IS_NEG );
279
280 case 0x90: // BCC
281 BRANCH( !(c & 0x100) )
282
283 case 0x30: // BMI
284 BRANCH( IS_NEG )
285
286 case 0x50: // BVC
287 BRANCH( !(flags & v40) )
288
289 case 0x70: // BVS
290 BRANCH( flags & v40 )
291
292 case 0xB0: // BCS
293 BRANCH( c & 0x100 )
294
295 case 0x80: // BRA
296 branch_taken:
297 BRANCH_( true, 0 );
298
299 case 0xFF:
300 #ifdef IDLE_ADDR
301 if ( pc == IDLE_ADDR + 1 )
302 goto idle_done;
303 #endif
304
305 pc = (uint16_t) pc;
306
307 case 0x0F: // BBRn
308 case 0x1F:
309 case 0x2F:
310 case 0x3F:
311 case 0x4F:
312 case 0x5F:
313 case 0x6F:
314 case 0x7F:
315 case 0x8F: // BBSn
316 case 0x9F:
317 case 0xAF:
318 case 0xBF:
319 case 0xCF:
320 case 0xDF:
321 case 0xEF: {
322 // Make two copies of bits, one negated
323 int t = 0x101 * READ_LOW( data );
324 t ^= 0xFF;
325 pc++;
326 data = GET_MSB();
327 BRANCH( t & (1 << (opcode >> 4)) )
328 }
329
330 case 0x4C: // JMP abs
331 pc = GET_ADDR();
332 goto loop;
333
334 case 0x7C: // JMP (ind+X)
335 data += x;
336 case 0x6C:{// JMP (ind)
337 data += 0x100 * GET_MSB();
338 pc = GET_LE16( &READ_CODE( data ) );
339 goto loop;
340 }
341
342// Subroutine
343
344 case 0x44: // BSR
345 WRITE_STACK( SP( -1 ), pc >> 8 );
346 sp = SP( -2 );
347 WRITE_STACK( sp, pc );
348 goto branch_taken;
349
350 case 0x20: { // JSR
351 int temp = pc + 1;
352 pc = GET_ADDR();
353 WRITE_STACK( SP( -1 ), temp >> 8 );
354 sp = SP( -2 );
355 WRITE_STACK( sp, temp );
356 goto loop;
357 }
358
359 case 0x60: // RTS
360 pc = 1 + READ_STACK( sp );
361 pc += 0x100 * READ_STACK( SP( 1 ) );
362 sp = SP( 2 );
363 goto loop;
364
365 case 0x00: // BRK
366 goto handle_brk;
367
368// Common
369
370 case 0xBD:{// LDA abs,X
371 PAGE_PENALTY( data + x );
372 int addr = GET_ADDR() + x;
373 pc += 2;
374 READ_FAST( addr, nz );
375 a = nz;
376 goto loop;
377 }
378
379 case 0x9D:{// STA abs,X
380 int addr = GET_ADDR() + x;
381 pc += 2;
382 WRITE_FAST( addr, a );
383 goto loop;
384 }
385
386 case 0x95: // STA zp,x
387 data = BYTE( data + x );
388 case 0x85: // STA zp
389 pc++;
390 WRITE_LOW( data, a );
391 goto loop;
392
393 case 0xAE:{// LDX abs
394 int addr = GET_ADDR();
395 pc += 2;
396 READ_FAST( addr, nz );
397 x = nz;
398 goto loop;
399 }
400
401 case 0xA5: // LDA zp
402 a = nz = READ_LOW( data );
403 pc++;
404 goto loop;
405
406// Load/store
407
408 {
409 int addr;
410 case 0x91: // STA (ind),Y
411 addr = 0x100 * READ_LOW( BYTE( data + 1 ) );
412 addr += READ_LOW( data ) + y;
413 pc++;
414 goto sta_ptr;
415
416 case 0x81: // STA (ind,X)
417 data = BYTE( data + x );
418 case 0x92: // STA (ind)
419 addr = 0x100 * READ_LOW( BYTE( data + 1 ) );
420 addr += READ_LOW( data );
421 pc++;
422 goto sta_ptr;
423
424 case 0x99: // STA abs,Y
425 data += y;
426 case 0x8D: // STA abs
427 addr = data + 0x100 * GET_MSB();
428 pc += 2;
429 sta_ptr:
430 WRITE_FAST( addr, a );
431 goto loop;
432 }
433
434 {
435 int addr;
436 case 0xA1: // LDA (ind,X)
437 data = BYTE( data + x );
438 case 0xB2: // LDA (ind)
439 addr = 0x100 * READ_LOW( BYTE( data + 1 ) );
440 addr += READ_LOW( data );
441 pc++;
442 goto a_nz_read_addr;
443
444 case 0xB1:// LDA (ind),Y
445 addr = READ_LOW( data ) + y;
446 PAGE_PENALTY( addr );
447 addr += 0x100 * READ_LOW( BYTE( data + 1 ) );
448 pc++;
449 goto a_nz_read_addr;
450
451 case 0xB9: // LDA abs,Y
452 data += y;
453 PAGE_PENALTY( data );
454 case 0xAD: // LDA abs
455 addr = data + 0x100 * GET_MSB();
456 pc += 2;
457 a_nz_read_addr:
458 READ_FAST( addr, nz );
459 a = nz;
460 goto loop;
461 }
462
463 case 0xBE:{// LDX abs,y
464 PAGE_PENALTY( data + y );
465 int addr = GET_ADDR() + y;
466 pc += 2;
467 FLUSH_TIME();
468 x = nz = READ_MEM( addr );
469 CACHE_TIME();
470 goto loop;
471 }
472
473 case 0xB5: // LDA zp,x
474 a = nz = READ_LOW( BYTE( data + x ) );
475 pc++;
476 goto loop;
477
478 case 0xA9: // LDA #imm
479 pc++;
480 a = data;
481 nz = data;
482 goto loop;
483
484// Bit operations
485
486 case 0x3C: // BIT abs,x
487 data += x;
488 case 0x2C:{// BIT abs
489 int addr;
490 ADD_PAGE( addr );
491 FLUSH_TIME();
492 nz = READ_MEM( addr );
493 CACHE_TIME();
494 goto bit_common;
495 }
496 case 0x34: // BIT zp,x
497 data = BYTE( data + x );
498 case 0x24: // BIT zp
499 data = READ_LOW( data );
500 case 0x89: // BIT imm
501 nz = data;
502 bit_common:
503 pc++;
504 flags = (flags & ~v40) + (nz & v40);
505 if ( nz & a )
506 goto loop; // Z should be clear, and nz must be non-zero if nz & a is
507 nz <<= 8; // set Z flag without affecting N flag
508 goto loop;
509
510 {
511 int addr;
512
513 case 0xB3: // TST abs,x
514 addr = GET_MSB() + x;
515 goto tst_abs;
516
517 case 0x93: // TST abs
518 addr = GET_MSB();
519 tst_abs:
520 addr += 0x100 * instr [2];
521 pc++;
522 FLUSH_TIME();
523 nz = READ_MEM( addr );
524 CACHE_TIME();
525 goto tst_common;
526 }
527
528 case 0xA3: // TST zp,x
529 nz = READ_LOW( BYTE( GET_MSB() + x ) );
530 goto tst_common;
531
532 case 0x83: // TST zp
533 nz = READ_LOW( GET_MSB() );
534 tst_common:
535 pc += 2;
536 flags = (flags & ~v40) + (nz & v40);
537 if ( nz & data )
538 goto loop; // Z should be clear, and nz must be non-zero if nz & data is
539 nz <<= 8; // set Z flag without affecting N flag
540 goto loop;
541
542 {
543 int addr;
544 case 0x0C: // TSB abs
545 case 0x1C: // TRB abs
546 addr = GET_ADDR();
547 pc++;
548 goto txb_addr;
549
550 // TODO: everyone lists different behaviors for the flags flags, ugh
551 case 0x04: // TSB zp
552 case 0x14: // TRB zp
553 addr = data + ram_addr;
554 txb_addr:
555 FLUSH_TIME();
556 nz = a | READ_MEM( addr );
557 if ( opcode & 0x10 )
558 nz ^= a; // bits from a will already be set, so this clears them
559 flags = (flags & ~v40) + (nz & v40);
560 pc++;
561 WRITE_MEM( addr, nz );
562 CACHE_TIME();
563 goto loop;
564 }
565
566 case 0x07: // RMBn
567 case 0x17:
568 case 0x27:
569 case 0x37:
570 case 0x47:
571 case 0x57:
572 case 0x67:
573 case 0x77:
574 pc++;
575 READ_LOW( data ) &= ~(1 << (opcode >> 4));
576 goto loop;
577
578 case 0x87: // SMBn
579 case 0x97:
580 case 0xA7:
581 case 0xB7:
582 case 0xC7:
583 case 0xD7:
584 case 0xE7:
585 case 0xF7:
586 pc++;
587 READ_LOW( data ) |= 1 << ((opcode >> 4) - 8);
588 goto loop;
589
590// Load/store
591
592 case 0x9E: // STZ abs,x
593 data += x;
594 case 0x9C: // STZ abs
595 ADD_PAGE( data );
596 pc++;
597 FLUSH_TIME();
598 WRITE_MEM( data, 0 );
599 CACHE_TIME();
600 goto loop;
601
602 case 0x74: // STZ zp,x
603 data = BYTE( data + x );
604 case 0x64: // STZ zp
605 pc++;
606 WRITE_LOW( data, 0 );
607 goto loop;
608
609 case 0x94: // STY zp,x
610 data = BYTE( data + x );
611 case 0x84: // STY zp
612 pc++;
613 WRITE_LOW( data, y );
614 goto loop;
615
616 case 0x96: // STX zp,y
617 data = BYTE( data + y );
618 case 0x86: // STX zp
619 pc++;
620 WRITE_LOW( data, x );
621 goto loop;
622
623 case 0xB6: // LDX zp,y
624 data = BYTE( data + y );
625 case 0xA6: // LDX zp
626 data = READ_LOW( data );
627 case 0xA2: // LDX #imm
628 pc++;
629 x = data;
630 nz = data;
631 goto loop;
632
633 case 0xB4: // LDY zp,x
634 data = BYTE( data + x );
635 case 0xA4: // LDY zp
636 data = READ_LOW( data );
637 case 0xA0: // LDY #imm
638 pc++;
639 y = data;
640 nz = data;
641 goto loop;
642
643 case 0xBC: // LDY abs,X
644 data += x;
645 PAGE_PENALTY( data );
646 case 0xAC:{// LDY abs
647 int addr = data + 0x100 * GET_MSB();
648 pc += 2;
649 FLUSH_TIME();
650 y = nz = READ_MEM( addr );
651 CACHE_TIME();
652 goto loop;
653 }
654
655 {
656 int temp;
657 case 0x8C: // STY abs
658 temp = y;
659 if ( 0 )
660 case 0x8E: // STX abs
661 temp = x;
662 int addr = GET_ADDR();
663 pc += 2;
664 FLUSH_TIME();
665 WRITE_MEM( addr, temp );
666 CACHE_TIME();
667 goto loop;
668 }
669
670// Compare
671
672 case 0xEC:{// CPX abs
673 int addr = GET_ADDR();
674 pc++;
675 FLUSH_TIME();
676 data = READ_MEM( addr );
677 CACHE_TIME();
678 goto cpx_data;
679 }
680
681 case 0xE4: // CPX zp
682 data = READ_LOW( data );
683 case 0xE0: // CPX #imm
684 cpx_data:
685 nz = x - data;
686 pc++;
687 c = ~nz;
688 nz = BYTE( nz );
689 goto loop;
690
691 case 0xCC:{// CPY abs
692 int addr = GET_ADDR();
693 pc++;
694 FLUSH_TIME();
695 data = READ_MEM( addr );
696 CACHE_TIME();
697 goto cpy_data;
698 }
699
700 case 0xC4: // CPY zp
701 data = READ_LOW( data );
702 case 0xC0: // CPY #imm
703 cpy_data:
704 nz = y - data;
705 pc++;
706 c = ~nz;
707 nz = BYTE( nz );
708 goto loop;
709
710// Logical
711
712#define ARITH_ADDR_MODES( op )\
713 case op - 0x04: /* (ind,x) */\
714 data = BYTE( data + x );\
715 case op + 0x0D: /* (ind) */\
716 data = 0x100 * READ_LOW( BYTE( data + 1 ) ) + READ_LOW( data );\
717 goto ptr##op;\
718 case op + 0x0C:{/* (ind),y */\
719 int temp = READ_LOW( data ) + y;\
720 PAGE_PENALTY( temp );\
721 data = temp + 0x100 * READ_LOW( BYTE( data + 1 ) );\
722 goto ptr##op;\
723 }\
724 case op + 0x10: /* zp,X */\
725 data = BYTE( data + x );\
726 case op + 0x00: /* zp */\
727 data = READ_LOW( data );\
728 goto imm##op;\
729 case op + 0x14: /* abs,Y */\
730 data += y;\
731 goto ind##op;\
732 case op + 0x18: /* abs,X */\
733 data += x;\
734 ind##op:\
735 PAGE_PENALTY( data );\
736 case op + 0x08: /* abs */\
737 ADD_PAGE( data );\
738 ptr##op:\
739 FLUSH_TIME();\
740 data = READ_MEM( data );\
741 CACHE_TIME();\
742 case op + 0x04: /* imm */\
743 imm##op:
744
745 ARITH_ADDR_MODES( 0xC5 ) // CMP
746 nz = a - data;
747 pc++;
748 c = ~nz;
749 nz = BYTE( nz );
750 goto loop;
751
752 ARITH_ADDR_MODES( 0x25 ) // AND
753 nz = (a &= data);
754 pc++;
755 goto loop;
756
757 ARITH_ADDR_MODES( 0x45 ) // EOR
758 nz = (a ^= data);
759 pc++;
760 goto loop;
761
762 ARITH_ADDR_MODES( 0x05 ) // ORA
763 nz = (a |= data);
764 pc++;
765 goto loop;
766
767// Add/subtract
768
769 ARITH_ADDR_MODES( 0xE5 ) // SBC
770 data ^= 0xFF;
771 goto adc_imm;
772
773 ARITH_ADDR_MODES( 0x65 ) // ADC
774 adc_imm: {
775 /* if ( flags & d08 )
776 dprintf( "Decimal mode not supported\n" ); */
777 int carry = c >> 8 & 1;
778 int ov = (a ^ 0x80) + carry + SBYTE( data );
779 flags = (flags & ~v40) + (ov >> 2 & v40);
780 c = nz = a + data + carry;
781 pc++;
782 a = BYTE( nz );
783 goto loop;
784 }
785
786// Shift/rotate
787
788 case 0x4A: // LSR A
789 c = 0;
790 case 0x6A: // ROR A
791 nz = c >> 1 & 0x80;
792 c = a << 8;
793 nz += a >> 1;
794 a = nz;
795 goto loop;
796
797 case 0x0A: // ASL A
798 nz = a << 1;
799 c = nz;
800 a = BYTE( nz );
801 goto loop;
802
803 case 0x2A: { // ROL A
804 nz = a << 1;
805 int temp = c >> 8 & 1;
806 c = nz;
807 nz += temp;
808 a = BYTE( nz );
809 goto loop;
810 }
811
812 case 0x5E: // LSR abs,X
813 data += x;
814 case 0x4E: // LSR abs
815 c = 0;
816 case 0x6E: // ROR abs
817 ror_abs: {
818 ADD_PAGE( data );
819 FLUSH_TIME();
820 int temp = READ_MEM( data );
821 nz = (c >> 1 & 0x80) + (temp >> 1);
822 c = temp << 8;
823 goto rotate_common;
824 }
825
826 case 0x3E: // ROL abs,X
827 data += x;
828 goto rol_abs;
829
830 case 0x1E: // ASL abs,X
831 data += x;
832 case 0x0E: // ASL abs
833 c = 0;
834 case 0x2E: // ROL abs
835 rol_abs:
836 ADD_PAGE( data );
837 nz = c >> 8 & 1;
838 FLUSH_TIME();
839 nz += (c = READ_MEM( data ) << 1);
840 rotate_common:
841 pc++;
842 WRITE_MEM( data, BYTE( nz ) );
843 CACHE_TIME();
844 goto loop;
845
846 case 0x7E: // ROR abs,X
847 data += x;
848 goto ror_abs;
849
850 case 0x76: // ROR zp,x
851 data = BYTE( data + x );
852 goto ror_zp;
853
854 case 0x56: // LSR zp,x
855 data = BYTE( data + x );
856 case 0x46: // LSR zp
857 c = 0;
858 case 0x66: // ROR zp
859 ror_zp: {
860 int temp = READ_LOW( data );
861 nz = (c >> 1 & 0x80) + (temp >> 1);
862 c = temp << 8;
863 goto write_nz_zp;
864 }
865
866 case 0x36: // ROL zp,x
867 data = BYTE( data + x );
868 goto rol_zp;
869
870 case 0x16: // ASL zp,x
871 data = BYTE( data + x );
872 case 0x06: // ASL zp
873 c = 0;
874 case 0x26: // ROL zp
875 rol_zp:
876 nz = c >> 8 & 1;
877 nz += (c = READ_LOW( data ) << 1);
878 goto write_nz_zp;
879
880// Increment/decrement
881
882#define INC_DEC( reg, n ) reg = BYTE( nz = reg + n ); goto loop;
883
884 case 0x1A: // INA
885 INC_DEC( a, +1 )
886
887 case 0xE8: // INX
888 INC_DEC( x, +1 )
889
890 case 0xC8: // INY
891 INC_DEC( y, +1 )
892
893 case 0x3A: // DEA
894 INC_DEC( a, -1 )
895
896 case 0xCA: // DEX
897 INC_DEC( x, -1 )
898
899 case 0x88: // DEY
900 INC_DEC( y, -1 )
901
902 case 0xF6: // INC zp,x
903 data = BYTE( data + x );
904 case 0xE6: // INC zp
905 nz = 1;
906 goto add_nz_zp;
907
908 case 0xD6: // DEC zp,x
909 data = BYTE( data + x );
910 case 0xC6: // DEC zp
911 nz = -1;
912 add_nz_zp:
913 nz += READ_LOW( data );
914 write_nz_zp:
915 pc++;
916 WRITE_LOW( data, nz );
917 goto loop;
918
919 case 0xFE: // INC abs,x
920 data = x + GET_ADDR();
921 goto inc_ptr;
922
923 case 0xEE: // INC abs
924 data = GET_ADDR();
925 inc_ptr:
926 nz = 1;
927 goto inc_common;
928
929 case 0xDE: // DEC abs,x
930 data = x + GET_ADDR();
931 goto dec_ptr;
932
933 case 0xCE: // DEC abs
934 data = GET_ADDR();
935 dec_ptr:
936 nz = -1;
937 inc_common:
938 FLUSH_TIME();
939 pc += 2;
940 nz += READ_MEM( data );
941 WRITE_MEM( data, BYTE( nz ) );
942 CACHE_TIME();
943 goto loop;
944
945// Transfer
946
947 case 0xA8: // TAY
948 y = nz = a;
949 goto loop;
950
951 case 0x98: // TYA
952 a = nz = y;
953 goto loop;
954
955 case 0xAA: // TAX
956 x = nz = a;
957 goto loop;
958
959 case 0x8A: // TXA
960 a = nz = x;
961 goto loop;
962
963 case 0x9A: // TXS
964 SET_SP( x ); // verified (no flag change)
965 goto loop;
966
967 case 0xBA: // TSX
968 x = nz = GET_SP();
969 goto loop;
970
971 #define SWAP_REGS( r1, r2 ) {\
972 int t = r1;\
973 r1 = r2;\
974 r2 = t;\
975 goto loop;\
976 }
977
978 case 0x02: // SXY
979 SWAP_REGS( x, y );
980
981 case 0x22: // SAX
982 SWAP_REGS( a, x );
983
984 case 0x42: // SAY
985 SWAP_REGS( a, y );
986
987 case 0x62: // CLA
988 a = 0;
989 goto loop;
990
991 case 0x82: // CLX
992 x = 0;
993 goto loop;
994
995 case 0xC2: // CLY
996 y = 0;
997 goto loop;
998
999// Stack
1000
1001 case 0x48: // PHA
1002 sp = SP( -1 );
1003 WRITE_STACK( sp, a );
1004 goto loop;
1005
1006 case 0x68: // PLA
1007 a = nz = READ_STACK( sp );
1008 sp = SP( 1 );
1009 goto loop;
1010
1011 case 0xDA: // PHX
1012 sp = SP( -1 );
1013 WRITE_STACK( sp, x );
1014 goto loop;
1015
1016 case 0x5A: // PHY
1017 sp = SP( -1 );
1018 WRITE_STACK( sp, y );
1019 goto loop;
1020
1021 case 0x40:{// RTI
1022 pc = READ_STACK( SP( 1 ) );
1023 pc += READ_STACK( SP( 2 ) ) * 0x100;
1024 int temp = READ_STACK( sp );
1025 sp = SP( 3 );
1026 data = flags;
1027 SET_FLAGS( temp );
1028 cpu->r.flags = flags; // update externally-visible I flag
1029 if ( (data ^ flags) & i04 )
1030 {
1031 hes_time_t new_time = cpu->end_time_;
1032 if ( !(flags & i04) && new_time > cpu->irq_time_ )
1033 new_time = cpu->irq_time_;
1034 int delta = s.base - new_time;
1035 s.base = new_time;
1036 s_time += delta;
1037 }
1038 goto loop;
1039 }
1040
1041 case 0xFA: // PLX
1042 x = nz = READ_STACK( sp );
1043 sp = SP( 1 );
1044 goto loop;
1045
1046 case 0x7A: // PLY
1047 y = nz = READ_STACK( sp );
1048 sp = SP( 1 );
1049 goto loop;
1050
1051 case 0x28:{// PLP
1052 int temp = READ_STACK( sp );
1053 sp = SP( 1 );
1054 int changed = flags ^ temp;
1055 SET_FLAGS( temp );
1056 if ( !(changed & i04) )
1057 goto loop; // I flag didn't change
1058 if ( flags & i04 )
1059 goto handle_sei;
1060 goto handle_cli;
1061 }
1062
1063 case 0x08:{// PHP
1064 int temp;
1065 GET_FLAGS( temp );
1066 sp = SP( -1 );
1067 WRITE_STACK( sp, temp | b10 );
1068 goto loop;
1069 }
1070
1071// Flags
1072
1073 case 0x38: // SEC
1074 c = 0x100;
1075 goto loop;
1076
1077 case 0x18: // CLC
1078 c = 0;
1079 goto loop;
1080
1081 case 0xB8: // CLV
1082 flags &= ~v40;
1083 goto loop;
1084
1085 case 0xD8: // CLD
1086 flags &= ~d08;
1087 goto loop;
1088
1089 case 0xF8: // SED
1090 flags |= d08;
1091 goto loop;
1092
1093 case 0x58: // CLI
1094 if ( !(flags & i04) )
1095 goto loop;
1096 flags &= ~i04;
1097 handle_cli: {
1098 //dprintf( "CLI at %d\n", TIME );
1099 cpu->r.flags = flags; // update externally-visible I flag
1100 int delta = s.base - cpu->irq_time_;
1101 if ( delta <= 0 )
1102 {
1103 if ( TIME() < cpu->irq_time_ )
1104 goto loop;
1105 goto delayed_cli;
1106 }
1107 s.base = cpu->irq_time_;
1108 s_time += delta;
1109 if ( s_time < 0 )
1110 goto loop;
1111
1112 if ( delta >= s_time + 1 )
1113 {
1114 // delayed irq until after next instruction
1115 s.base += s_time + 1;
1116 s_time = -1;
1117 cpu->irq_time_ = s.base; // TODO: remove, as only to satisfy debug check in loop
1118 goto loop;
1119 }
1120
1121 // TODO: implement
1122 delayed_cli:
1123 dprintf( "Delayed CLI not supported\n" );
1124 goto loop;
1125 }
1126
1127 case 0x78: // SEI
1128 if ( flags & i04 )
1129 goto loop;
1130 flags |= i04;
1131 handle_sei: {
1132 cpu->r.flags = flags; // update externally-visible I flag
1133 int delta = s.base - cpu->end_time_;
1134 s.base = cpu->end_time_;
1135 s_time += delta;
1136 if ( s_time < 0 )
1137 goto loop;
1138
1139 dprintf( "Delayed SEI not supported\n" );
1140 goto loop;
1141 }
1142
1143// Special
1144
1145 case 0x53:{// TAM
1146 int bits = data; // avoid using data across function call
1147 pc++;
1148 for ( int i = 0; i < 8; i++ )
1149 if ( bits & (1 << i) )
1150 SET_MMR( i, a );
1151 goto loop;
1152 }
1153
1154 case 0x43:{// TMA
1155 pc++;
1156 byte const* in = cpu->mmr;
1157 do
1158 {
1159 if ( data & 1 )
1160 a = *in;
1161 in++;
1162 }
1163 while ( (data >>= 1) != 0 );
1164 goto loop;
1165 }
1166
1167 case 0x03: // ST0
1168 case 0x13: // ST1
1169 case 0x23:{// ST2
1170 int addr = opcode >> 4;
1171 if ( addr )
1172 addr++;
1173 pc++;
1174 FLUSH_TIME();
1175 WRITE_VDP( addr, data );
1176 CACHE_TIME();
1177 goto loop;
1178 }
1179
1180 case 0xEA: // NOP
1181 goto loop;
1182
1183 case 0x54: // CSL
1184 dprintf( "CSL not supported\n" );
1185 illegal_encountered = true;
1186 goto loop;
1187
1188 case 0xD4: // CSH
1189 goto loop;
1190
1191 case 0xF4: { // SET
1192 //int operand = GET_MSB();
1193 dprintf( "SET not handled\n" );
1194 //switch ( data )
1195 //{
1196 //}
1197 illegal_encountered = true;
1198 goto loop;
1199 }
1200
1201// Block transfer
1202
1203 {
1204 int in_alt;
1205 int in_inc;
1206 int out_alt;
1207 int out_inc;
1208
1209 case 0xE3: // TIA
1210 in_alt = 0;
1211 goto bxfer_alt;
1212
1213 case 0xF3: // TAI
1214 in_alt = 1;
1215 bxfer_alt:
1216 in_inc = in_alt ^ 1;
1217 out_alt = in_inc;
1218 out_inc = in_alt;
1219 goto bxfer;
1220
1221 case 0xD3: // TIN
1222 in_inc = 1;
1223 out_inc = 0;
1224 goto bxfer_no_alt;
1225
1226 case 0xC3: // TDD
1227 in_inc = -1;
1228 out_inc = -1;
1229 goto bxfer_no_alt;
1230
1231 case 0x73: // TII
1232 in_inc = 1;
1233 out_inc = 1;
1234 bxfer_no_alt:
1235 in_alt = 0;
1236 out_alt = 0;
1237 bxfer:
1238 {
1239 int in = GET_LE16( instr + 0 );
1240 int out = GET_LE16( instr + 2 );
1241 int count = GET_LE16( instr + 4 );
1242 if ( !count )
1243 count = 0x10000;
1244 pc += 6;
1245 WRITE_STACK( SP( -1 ), y );
1246 WRITE_STACK( SP( -2 ), a );
1247 WRITE_STACK( SP( -3 ), x );
1248 FLUSH_TIME();
1249 do
1250 {
1251 // TODO: reads from $0800-$1400 in I/O page should do I/O
1252 int t = READ_MEM( in );
1253 in = WORD( in + in_inc );
1254 s.time += 6;
1255 if ( in_alt )
1256 in_inc = -in_inc;
1257 WRITE_MEM( out, t );
1258 out = WORD( out + out_inc );
1259 if ( out_alt )
1260 out_inc = -out_inc;
1261 }
1262 while ( --count );
1263 CACHE_TIME();
1264 goto loop;
1265 }
1266 }
1267
1268// Illegal
1269
1270 default:
1271 check( (unsigned) opcode <= 0xFF );
1272 dprintf( "Illegal opcode $%02X at $%04X\n", (int) opcode, (int) pc - 1 );
1273 illegal_encountered = true;
1274 goto loop;
1275 }
1276 assert( false ); // catch missing 'goto loop' or accidental 'break'
1277
1278 int result_;
1279handle_brk:
1280 pc++;
1281 result_ = 6;
1282
1283interrupt:
1284 {
1285 s_time += 7;
1286
1287 // Save PC and read vector
1288 WRITE_STACK( SP( -1 ), pc >> 8 );
1289 WRITE_STACK( SP( -2 ), pc );
1290 pc = GET_LE16( &READ_CODE( 0xFFF0 ) + result_ );
1291
1292 // Save flags
1293 int temp;
1294 GET_FLAGS( temp );
1295 if ( result_ == 6 )
1296 temp |= b10; // BRK sets B bit
1297 sp = SP( -3 );
1298 WRITE_STACK( sp, temp );
1299
1300 // Update I flag in externally-visible flags
1301 flags &= ~d08;
1302 cpu->r.flags = (flags |= i04);
1303
1304 // Update time
1305 int delta = s.base - cpu->end_time_;
1306 if ( delta >= 0 )
1307 goto loop;
1308 s_time += delta;
1309 s.base = cpu->end_time_;
1310 goto loop;
1311 }
1312
1313idle_done:
1314 s_time = 0;
1315
1316out_of_time:
1317 pc--;
1318
1319 // Optional action that triggers interrupt or changes irq/end time
1320 #ifdef CPU_DONE
1321 {
1322 CPU_DONE( result_ );
1323 if ( result_ >= 0 )
1324 goto interrupt;
1325 if ( s_time < 0 )
1326 goto loop;
1327 }
1328 #endif
1329
1330 // Flush cached state
1331 cpu->r.pc = pc;
1332 cpu->r.sp = GET_SP();
1333 cpu->r.a = a;
1334 cpu->r.x = x;
1335 cpu->r.y = y;
1336
1337 int temp;
1338 GET_FLAGS( temp );
1339 cpu->r.flags = temp;
1340
1341 cpu->cpu_state_.base = s.base;
1342 cpu->cpu_state_.time = s_time;
1343 cpu->cpu_state = &cpu->cpu_state_;
1344}
diff --git a/apps/codecs/libgme/hes_emu.c b/apps/codecs/libgme/hes_emu.c
index a428bee3fd..8ddbb9dc29 100644
--- a/apps/codecs/libgme/hes_emu.c
+++ b/apps/codecs/libgme/hes_emu.c
@@ -21,28 +21,14 @@ int const vdp_mask = 0x02;
21int const i_flag_mask = 0x04; 21int const i_flag_mask = 0x04;
22int const unmapped = 0xFF; 22int const unmapped = 0xFF;
23 23
24long const period_60hz = 262 * 455L; // scanlines * clocks per scanline 24int const period_60hz = 262 * 455; // scanlines * clocks per scanline
25
26int const stereo = 2; // number of channels for stereo
27int const silence_max = 6; // seconds
28int const silence_threshold = 0x10;
29long const fade_block_size = 512;
30int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
31 25
32const char gme_wrong_file_type [] = "Wrong file type for this emulator"; 26const char gme_wrong_file_type [] = "Wrong file type for this emulator";
33 27
34static void clear_track_vars( struct Hes_Emu* this ) 28static void clear_track_vars( struct Hes_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 = (blargg_long)(LONG_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
48void Hes_init( struct Hes_Emu* this ) 34void Hes_init( struct Hes_Emu* this )
@@ -52,15 +38,12 @@ void Hes_init( struct Hes_Emu* this )
52 this->tempo_ = (int)(FP_ONE_TEMPO); 38 this->tempo_ = (int)(FP_ONE_TEMPO);
53 39
54 // defaults 40 // defaults
55 this->max_initial_silence = 2; 41 this->tfilter = *track_get_setup( &this->track_filter );
56 this->ignore_silence = false; 42 this->tfilter.max_initial = 2;
57 43 this->tfilter.lookahead = 6;
58 // Unload 44 this->track_filter.silence_ignored_ = false;
59 this->voice_count_ = 0;
60 clear_track_vars( this );
61 45
62 this->timer.raw_load = 0; 46 this->timer.raw_load = 0;
63 this->silence_lookahead = 6;
64 Sound_set_gain( this, (int)(FP_ONE_GAIN*1.11) ); 47 Sound_set_gain( this, (int)(FP_ONE_GAIN*1.11) );
65 48
66 Rom_init( &this->rom, 0x2000 ); 49 Rom_init( &this->rom, 0x2000 );
@@ -71,6 +54,11 @@ void Hes_init( struct Hes_Emu* this )
71 54
72 /* Set default track count */ 55 /* Set default track count */
73 this->track_count = 255; 56 this->track_count = 255;
57
58 // clears fields
59 this->voice_count_ = 0;
60 this->voice_types_ = 0;
61 clear_track_vars( this );
74} 62}
75 63
76static blargg_err_t check_hes_header( void const* header ) 64static blargg_err_t check_hes_header( void const* header )
@@ -82,10 +70,12 @@ static blargg_err_t check_hes_header( void const* header )
82 70
83// Setup 71// Setup
84 72
85blargg_err_t Hes_load( struct Hes_Emu* this, void* data, long size ) 73blargg_err_t Hes_load_mem( struct Hes_Emu* this, void* data, long size )
86{ 74{
87 // Unload 75 // Unload
88 this->voice_count_ = 0; 76 this->voice_count_ = 0;
77 this->track_count = 255;
78 this->m3u.size = 0;
89 clear_track_vars( this ); 79 clear_track_vars( this );
90 80
91 assert( offsetof (struct header_t,unused [4]) == header_size ); 81 assert( offsetof (struct header_t,unused [4]) == header_size );
@@ -106,15 +96,15 @@ blargg_err_t Hes_load( struct Hes_Emu* this, void* data, long size )
106 // many files have bad sizes in the only block, so it's simpler to 96 // many files have bad sizes in the only block, so it's simpler to
107 // just try to load the damn data as best as possible. 97 // just try to load the damn data as best as possible.
108 98
109 long addr = get_le32( this->header.addr ); 99 int addr = get_le32( this->header.addr );
110 /* long rom_size = get_le32( this->header.size ); */ 100 /* int rom_size = get_le32( this->header.size ); */
111 long const rom_max = 0x100000; 101 int const rom_max = 0x100000;
112 if ( addr & ~(rom_max - 1) ) 102 if ( (unsigned) addr >= (unsigned) rom_max )
113 { 103 {
114 /* warning( "Invalid address" ); */ 104 /* warning( "Invalid address" ); */
115 addr &= rom_max - 1; 105 addr &= rom_max - 1;
116 } 106 }
117 /* if ( (unsigned long) (addr + size) > (unsigned long) rom_max ) 107 /* if ( (unsigned) (addr + size) > (unsigned) rom_max )
118 warning( "Invalid size" ); 108 warning( "Invalid size" );
119 109
120 if ( rom_size != rom.file_size() ) 110 if ( rom_size != rom.file_size() )
@@ -130,6 +120,10 @@ blargg_err_t Hes_load( struct Hes_Emu* this, void* data, long size )
130 Rom_set_addr( &this->rom, addr ); 120 Rom_set_addr( &this->rom, addr );
131 121
132 this->voice_count_ = osc_count + adpcm_osc_count; 122 this->voice_count_ = osc_count + adpcm_osc_count;
123 static int const types [osc_count + adpcm_osc_count] = {
124 wave_type+0, wave_type+1, wave_type+2, wave_type+3, mixed_type+0, mixed_type+1, mixed_type+2
125 };
126 this->voice_types_ = types;
133 127
134 Apu_volume( &this->apu, this->gain_ ); 128 Apu_volume( &this->apu, this->gain_ );
135 Adpcm_volume( &this->adpcm, this->gain_ ); 129 Adpcm_volume( &this->adpcm, this->gain_ );
@@ -137,21 +131,17 @@ blargg_err_t Hes_load( struct Hes_Emu* this, void* data, long size )
137 // Setup buffer 131 // Setup buffer
138 this->clock_rate_ = 7159091; 132 this->clock_rate_ = 7159091;
139 Buffer_clock_rate( &this->stereo_buf, 7159091 ); 133 Buffer_clock_rate( &this->stereo_buf, 7159091 );
134 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count_, this->voice_types_ ) );
140 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); 135 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
141 136
142 Sound_set_tempo( this, this->tempo_ ); 137 Sound_set_tempo( this, this->tempo_ );
143 Sound_mute_voices( this, this->mute_mask_ ); 138 Sound_mute_voices( this, this->mute_mask_ );
144 139
145 // Reset track count
146 this->track_count = 255;
147 this->m3u.size = 0;
148 return 0; 140 return 0;
149} 141}
150 142
151
152// Emulation 143// Emulation
153 144
154void recalc_timer_load( struct Hes_Emu* this );
155void recalc_timer_load( struct Hes_Emu* this ) 145void recalc_timer_load( struct Hes_Emu* this )
156{ 146{
157 this->timer.load = this->timer.raw_load * this->timer_base + 1; 147 this->timer.load = this->timer.raw_load * this->timer_base + 1;
@@ -159,9 +149,25 @@ void recalc_timer_load( struct Hes_Emu* this )
159 149
160// Hardware 150// Hardware
161 151
162void irq_changed( struct Hes_Emu* this ); 152void run_until( struct Hes_Emu* this, hes_time_t present )
163void run_until( struct Hes_Emu* this, hes_time_t present ); 153{
164void Cpu_write_vdp( struct Hes_Emu* this, int addr, int data ) 154 while ( this->vdp.next_vbl < present )
155 this->vdp.next_vbl += this->play_period;
156
157 hes_time_t elapsed = present - this->timer.last_time;
158 if ( elapsed > 0 )
159 {
160 if ( this->timer.enabled )
161 {
162 this->timer.count -= elapsed;
163 if ( this->timer.count <= 0 )
164 this->timer.count += this->timer.load;
165 }
166 this->timer.last_time = present;
167 }
168}
169
170void write_vdp( struct Hes_Emu* this, int addr, int data )
165{ 171{
166 switch ( addr ) 172 switch ( addr )
167 { 173 {
@@ -178,77 +184,33 @@ void Cpu_write_vdp( struct Hes_Emu* this, int addr, int data )
178 this->vdp.control = data; 184 this->vdp.control = data;
179 irq_changed( this ); 185 irq_changed( this );
180 } 186 }
181 else 187 /* else
182 { 188 {
183 dprintf( "VDP not supported: $%02X <- $%02X\n", this->vdp.latch, data ); 189 dprintf( "VDP not supported: $%02X <- $%02X\n", vdp.latch, data );
184 } 190 } */
185 break; 191 break;
186 192
187 case 3: 193 case 3:
188 dprintf( "VDP MSB not supported: $%02X <- $%02X\n", this->vdp.latch, data ); 194 /* dprintf( "VDP MSB not supported: $%02X <- $%02X\n", vdp.latch, data ); */
189 break; 195 break;
190 } 196 }
191} 197}
192 198
193int Cpu_done( struct Hes_Emu* this ) 199void write_mem_( struct Hes_Emu* this, hes_addr_t addr, int data )
194{
195 check( time() >= end_time() ||
196 (!(r.status & i_flag_mask) && time() >= irq_time()) );
197
198 if ( !(this->cpu.r.status & i_flag_mask) )
199 {
200 hes_time_t present = Cpu_time( &this->cpu );
201
202 if ( this->irq.timer <= present && !(this->irq.disables & timer_mask) )
203 {
204 this->timer.fired = true;
205 this->irq.timer = (hes_time_t)future_hes_time;
206 irq_changed( this ); // overkill, but not worth writing custom code
207 #if defined (GME_FRAME_HOOK_DEFINED)
208 {
209 unsigned const threshold = period_60hz / 30;
210 unsigned long elapsed = present - last_frame_hook;
211 if ( elapsed - period_60hz + threshold / 2 < threshold )
212 {
213 last_frame_hook = present;
214 GME_FRAME_HOOK( this );
215 }
216 }
217 #endif
218 return 0x0A;
219 }
220
221 if ( this->irq.vdp <= present && !(this->irq.disables & vdp_mask) )
222 {
223 // work around for bugs with music not acknowledging VDP
224 //run_until( present );
225 //irq.vdp = future_hes_time;
226 //irq_changed();
227 #if defined(GME_FRAME_HOOK_DEFINED)
228 last_frame_hook = present;
229 GME_FRAME_HOOK( this );
230 #endif
231 return 0x08;
232 }
233 }
234 return 0;
235}
236
237void Emu_cpu_write( struct Hes_Emu* this, hes_addr_t addr, int data )
238{ 200{
239 hes_time_t time = Cpu_time( &this->cpu ); 201 hes_time_t time = Cpu_time( &this->cpu );
240 if ( (unsigned) (addr - start_addr) <= end_addr - start_addr ) 202 if ( (unsigned) (addr - apu_io_addr) < apu_io_size )
241 { 203 {
242 GME_APU_HOOK( this, addr - apu.start_addr, data ); 204 // Avoid going way past end when a long block xfer is writing to I/O space.
243 // avoid going way past end when a long block xfer is writing to I/O space 205 // Not a problem for other registers below because they don't write to
244 hes_time_t t = min( time, this->cpu.end_time + 8 ); 206 // Blip_Buffer.
207 hes_time_t t = min( time, Cpu_end_time( &this->cpu ) + 8 );
245 Apu_write_data( &this->apu, t, addr, data ); 208 Apu_write_data( &this->apu, t, addr, data );
246 return; 209 return;
247 } 210 }
248 211 if ( (unsigned) (addr - adpcm_io_addr) < adpcm_io_size )
249 if ( (unsigned) (addr - io_addr) < io_size )
250 { 212 {
251 hes_time_t t = min( time, this->cpu.end_time + 6 ); 213 hes_time_t t = min( time, Cpu_end_time( &this->cpu ) + 6 );
252 Adpcm_write_data( &this->adpcm, t, addr, data ); 214 Adpcm_write_data( &this->adpcm, t, addr, data );
253 return; 215 return;
254 } 216 }
@@ -258,7 +220,7 @@ void Emu_cpu_write( struct Hes_Emu* this, hes_addr_t addr, int data )
258 case 0x0000: 220 case 0x0000:
259 case 0x0002: 221 case 0x0002:
260 case 0x0003: 222 case 0x0003:
261 Cpu_write_vdp( this, addr, data ); 223 write_vdp( this, addr, data );
262 return; 224 return;
263 225
264 case 0x0C00: { 226 case 0x0C00: {
@@ -282,11 +244,8 @@ void Emu_cpu_write( struct Hes_Emu* this, hes_addr_t addr, int data )
282 case 0x1402: 244 case 0x1402:
283 run_until( this, time ); 245 run_until( this, time );
284 this->irq.disables = data; 246 this->irq.disables = data;
285 247 /* if ( (data & 0xF8) && (data & 0xF8) != 0xF8 ) // flag questionable values
286 // flag questionable values 248 dprintf( "Int mask: $%02X\n", data ); */
287 if ( (data & 0xF8) && (data & 0xF8) != 0xF8 ) {
288 dprintf( "Int mask: $%02X\n", data );
289 }
290 break; 249 break;
291 250
292 case 0x1403: 251 case 0x1403:
@@ -305,7 +264,7 @@ void Emu_cpu_write( struct Hes_Emu* this, hes_addr_t addr, int data )
305 return; 264 return;
306 265
307 default: 266 default:
308 dprintf( "unmapped write $%04X <- $%02X\n", addr, data ); 267 /* dprintf( "unmapped write $%04X <- $%02X\n", addr, data ); */
309 return; 268 return;
310#endif 269#endif
311 } 270 }
@@ -313,7 +272,7 @@ void Emu_cpu_write( struct Hes_Emu* this, hes_addr_t addr, int data )
313 irq_changed( this ); 272 irq_changed( this );
314} 273}
315 274
316int Emu_cpu_read( struct Hes_Emu* this, hes_addr_t addr ) 275int read_mem_( struct Hes_Emu* this, hes_addr_t addr )
317{ 276{
318 hes_time_t time = Cpu_time( &this->cpu ); 277 hes_time_t time = Cpu_time( &this->cpu );
319 addr &= page_size - 1; 278 addr &= page_size - 1;
@@ -322,21 +281,21 @@ int Emu_cpu_read( struct Hes_Emu* this, hes_addr_t addr )
322 case 0x0000: 281 case 0x0000:
323 if ( this->irq.vdp > time ) 282 if ( this->irq.vdp > time )
324 return 0; 283 return 0;
325 this->irq.vdp = (hes_time_t)future_hes_time; 284 this->irq.vdp = future_time;
326 run_until( this, time ); 285 run_until( this, time );
327 irq_changed( this ); 286 irq_changed( this );
328 return 0x20; 287 return 0x20;
329 288
330 case 0x0002: 289 /* case 0x0002:
331 case 0x0003: 290 case 0x0003:
332 dprintf( "VDP read not supported: %d\n", addr ); 291 dprintf( "VDP read not supported: %d\n", addr );
333 return 0; 292 return 0; */
334 293
335 case 0x0C01: 294 case 0x0C01:
336 //return timer.enabled; // TODO: remove? 295 //return timer.enabled; // TODO: remove?
337 case 0x0C00: 296 case 0x0C00:
338 run_until( this, time ); 297 run_until( this, time );
339 dprintf( "Timer count read\n" ); 298 /* dprintf( "Timer count read\n" ); */
340 return (unsigned) (this->timer.count - 1) / this->timer_base; 299 return (unsigned) (this->timer.count - 1) / this->timer_base;
341 300
342 case 0x1402: 301 case 0x1402:
@@ -349,7 +308,7 @@ int Emu_cpu_read( struct Hes_Emu* this, hes_addr_t addr )
349 if ( this->irq.vdp <= time ) status |= vdp_mask; 308 if ( this->irq.vdp <= time ) status |= vdp_mask;
350 return status; 309 return status;
351 } 310 }
352 311
353 case 0x180A: 312 case 0x180A:
354 case 0x180B: 313 case 0x180B:
355 case 0x180C: 314 case 0x180C:
@@ -358,71 +317,75 @@ int Emu_cpu_read( struct Hes_Emu* this, hes_addr_t addr )
358 317
359 #ifndef NDEBUG 318 #ifndef NDEBUG
360 case 0x1000: // I/O port 319 case 0x1000: // I/O port
361 // case 0x180C: // CD-ROM 320 //case 0x180C: // CD-ROM
362 // case 0x180D: 321 //case 0x180D:
363 break; 322 break;
364 323
365 default: 324 /* default:
366 dprintf( "unmapped read $%04X\n", addr ); 325 dprintf( "unmapped read $%04X\n", addr ); */
367 #endif 326 #endif
368 } 327 }
369 328
370 return unmapped; 329 return unmapped;
371} 330}
372 331
373// see hes_cpu_io.h for core read/write functions
374
375// Emulation
376
377void run_until( struct Hes_Emu* this, hes_time_t present )
378{
379 while ( this->vdp.next_vbl < present )
380 this->vdp.next_vbl += this->play_period;
381
382 hes_time_t elapsed = present - this->timer.last_time;
383 if ( elapsed > 0 )
384 {
385 if ( this->timer.enabled )
386 {
387 this->timer.count -= elapsed;
388 if ( this->timer.count <= 0 )
389 this->timer.count += this->timer.load;
390 }
391 this->timer.last_time = present;
392 }
393}
394
395void irq_changed( struct Hes_Emu* this ) 332void irq_changed( struct Hes_Emu* this )
396{ 333{
397 hes_time_t present = Cpu_time( &this->cpu ); 334 hes_time_t present = Cpu_time( &this->cpu );
398 335
399 if ( this->irq.timer > present ) 336 if ( this->irq.timer > present )
400 { 337 {
401 this->irq.timer = (hes_time_t)future_hes_time; 338 this->irq.timer = future_time;
402 if ( this->timer.enabled && !this->timer.fired ) 339 if ( this->timer.enabled && !this->timer.fired )
403 this->irq.timer = present + this->timer.count; 340 this->irq.timer = present + this->timer.count;
404 } 341 }
405 342
406 if ( this->irq.vdp > present ) 343 if ( this->irq.vdp > present )
407 { 344 {
408 this->irq.vdp = (hes_time_t)future_hes_time; 345 this->irq.vdp = future_time;
409 if ( this->vdp.control & 0x08 ) 346 if ( this->vdp.control & 0x08 )
410 this->irq.vdp = this->vdp.next_vbl; 347 this->irq.vdp = this->vdp.next_vbl;
411 } 348 }
412 349
413 hes_time_t time = (hes_time_t)future_hes_time; 350 hes_time_t time = future_time;
414 if ( !(this->irq.disables & timer_mask) ) time = this->irq.timer; 351 if ( !(this->irq.disables & timer_mask) ) time = this->irq.timer;
415 if ( !(this->irq.disables & vdp_mask) ) time = min( time, this->irq.vdp ); 352 if ( !(this->irq.disables & vdp_mask) ) time = min( time, this->irq.vdp );
416 353
417 // Set cpu irq time 354 Cpu_set_irq_time( &this->cpu, time );
418 this->cpu.state->time += Cpu_update_end_time( &this->cpu, this->cpu.r.status,
419 this->cpu.end_time, (this->cpu.irq_time = time) );
420} 355}
421 356
422static void adjust_time( blargg_long* time, hes_time_t delta ); 357int cpu_done( struct Hes_Emu* this )
423static void adjust_time( blargg_long* time, hes_time_t delta )
424{ 358{
425 if ( *time < (blargg_long)future_hes_time ) 359 check( Cpu_time( &this->cpu ) >= Cpu_end_time( &this->cpu ) ||
360 (!(this->cpu.r.flags & i_flag_mask) && Cpu_time( &this->cpu ) >= Cpu_irq_time( &this->cpu )) );
361
362 if ( !(this->cpu.r.flags & i_flag_mask) )
363 {
364 hes_time_t present = Cpu_time( &this->cpu );
365
366 if ( this->irq.timer <= present && !(this->irq.disables & timer_mask) )
367 {
368 this->timer.fired = true;
369 this->irq.timer = future_time;
370 irq_changed( this ); // overkill, but not worth writing custom code
371 return 0x0A;
372 }
373
374 if ( this->irq.vdp <= present && !(this->irq.disables & vdp_mask) )
375 {
376 // work around for bugs with music not acknowledging VDP
377 //run_until( present );
378 //irq.vdp = cpu.future_time;
379 //irq_changed();
380 return 0x08;
381 }
382 }
383 return -1;
384}
385
386static void adjust_time( hes_time_t* time, hes_time_t delta )
387{
388 if ( *time < future_time )
426 { 389 {
427 *time -= delta; 390 *time -= delta;
428 if ( *time < 0 ) 391 if ( *time < 0 )
@@ -430,15 +393,13 @@ static void adjust_time( blargg_long* time, hes_time_t delta )
430 } 393 }
431} 394}
432 395
433blargg_err_t run_clocks( struct Hes_Emu* this, blip_time_t* duration_ ); 396blargg_err_t end_frame( struct Hes_Emu* this, hes_time_t duration )
434blargg_err_t run_clocks( struct Hes_Emu* this, blip_time_t* duration_ )
435{ 397{
436 blip_time_t duration = *duration_; // cache 398 /* if ( run_cpu( this, duration ) )
399 warning( "Emulation error (illegal instruction)" ); */
400 run_cpu( this, duration );
437 401
438 Cpu_run( this, duration ); 402 check( Cpu_time( &this->cpu ) >= duration );
439 /* warning( "Emulation error (illegal instruction)" ); */
440
441 check( time() >= duration );
442 //check( time() - duration < 20 ); // Txx instruction could cause going way over 403 //check( time() - duration < 20 ); // Txx instruction could cause going way over
443 404
444 run_until( this, duration ); 405 run_until( this, duration );
@@ -446,15 +407,7 @@ blargg_err_t run_clocks( struct Hes_Emu* this, blip_time_t* duration_ )
446 // end time frame 407 // end time frame
447 this->timer.last_time -= duration; 408 this->timer.last_time -= duration;
448 this->vdp.next_vbl -= duration; 409 this->vdp.next_vbl -= duration;
449 #if defined (GME_FRAME_HOOK_DEFINED) 410 Cpu_end_frame( &this->cpu, duration );
450 last_frame_hook -= *duration;
451 #endif
452
453 // End cpu frame
454 this->cpu.state_.base -= duration;
455 if ( this->cpu.irq_time < (hes_time_t)future_hes_time ) this->cpu.irq_time -= duration;
456 if ( this->cpu.end_time < (hes_time_t)future_hes_time ) this->cpu.end_time -= duration;
457
458 adjust_time( &this->irq.timer, duration ); 411 adjust_time( &this->irq.timer, duration );
459 adjust_time( &this->irq.vdp, duration ); 412 adjust_time( &this->irq.vdp, duration );
460 Apu_end_frame( &this->apu, duration ); 413 Apu_end_frame( &this->apu, duration );
@@ -463,24 +416,31 @@ blargg_err_t run_clocks( struct Hes_Emu* this, blip_time_t* duration_ )
463 return 0; 416 return 0;
464} 417}
465 418
466blargg_err_t play_( struct Hes_Emu* this, long count, sample_t* out ); 419blargg_err_t run_clocks( struct Hes_Emu* this, blip_time_t* duration_ )
467blargg_err_t play_( struct Hes_Emu* this, long count, sample_t* out ) 420{
421 return end_frame( this, *duration_ );
422}
423
424blargg_err_t play_( void *emu, int count, sample_t out [] )
468{ 425{
469 long remain = count; 426 struct Hes_Emu* this = (struct Hes_Emu*) emu;
427
428 int remain = count;
470 while ( remain ) 429 while ( remain )
471 { 430 {
431 Buffer_disable_immediate_removal( &this->stereo_buf );
472 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain ); 432 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
473 if ( remain ) 433 if ( remain )
474 { 434 {
475 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) ) 435 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
476 { 436 {
477 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); 437 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
438
478 // Remute voices 439 // Remute voices
479 Sound_mute_voices( this, this->mute_mask_ ); 440 Sound_mute_voices( this, this->mute_mask_ );
480 } 441 }
481
482 int msec = Buffer_length( &this->stereo_buf ); 442 int msec = Buffer_length( &this->stereo_buf );
483 blip_time_t clocks_emulated = (blargg_long) msec * this->clock_rate_ / 1000; 443 blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
484 RETURN_ERR( run_clocks( this, &clocks_emulated ) ); 444 RETURN_ERR( run_clocks( this, &clocks_emulated ) );
485 assert( clocks_emulated ); 445 assert( clocks_emulated );
486 Buffer_end_frame( &this->stereo_buf, clocks_emulated ); 446 Buffer_end_frame( &this->stereo_buf, clocks_emulated );
@@ -489,10 +449,9 @@ blargg_err_t play_( struct Hes_Emu* this, long count, sample_t* out )
489 return 0; 449 return 0;
490} 450}
491 451
492
493// Music emu 452// Music emu
494 453
495blargg_err_t Hes_set_sample_rate( struct Hes_Emu* this, long rate ) 454blargg_err_t Hes_set_sample_rate( struct Hes_Emu* this, int rate )
496{ 455{
497 require( !this->sample_rate_ ); // sample rate can't be changed once set 456 require( !this->sample_rate_ ); // sample rate can't be changed once set
498 Buffer_init( &this->stereo_buf ); 457 Buffer_init( &this->stereo_buf );
@@ -502,6 +461,8 @@ blargg_err_t Hes_set_sample_rate( struct Hes_Emu* this, long rate )
502 Buffer_bass_freq( &this->stereo_buf, 60 ); 461 Buffer_bass_freq( &this->stereo_buf, 60 );
503 462
504 this->sample_rate_ = rate; 463 this->sample_rate_ = rate;
464 RETURN_ERR( track_init( &this->track_filter, this ) );
465 this->tfilter.max_silence = 6 * stereo * this->sample_rate_;
505 return 0; 466 return 0;
506} 467}
507 468
@@ -521,7 +482,7 @@ void Sound_mute_voices( struct Hes_Emu* this, int mask )
521 this->mute_mask_ = mask; 482 this->mute_mask_ = mask;
522 483
523 // Set adpcm voice 484 // Set adpcm voice
524 struct channel_t ch = Buffer_channel( &this->stereo_buf ); 485 struct channel_t ch = Buffer_channel( &this->stereo_buf, this->voice_count_ );
525 if ( mask & (1 << this->voice_count_ ) ) 486 if ( mask & (1 << this->voice_count_ ) )
526 Adpcm_set_output( &this->adpcm, 0, 0, 0, 0 ); 487 Adpcm_set_output( &this->adpcm, 0, 0, 0, 0 );
527 else 488 else
@@ -536,7 +497,8 @@ void Sound_mute_voices( struct Hes_Emu* this, int mask )
536 Apu_osc_output( &this->apu, i, 0, 0, 0 ); 497 Apu_osc_output( &this->apu, i, 0, 0, 0 );
537 } 498 }
538 else 499 else
539 { 500 {
501 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
540 assert( (ch.center && ch.left && ch.right) || 502 assert( (ch.center && ch.left && ch.right) ||
541 (!ch.center && !ch.left && !ch.right) ); // all or nothing 503 (!ch.center && !ch.left && !ch.right) ); // all or nothing
542 Apu_osc_output( &this->apu, i, ch.center, ch.left, ch.right ); 504 Apu_osc_output( &this->apu, i, ch.center, ch.left, ch.right );
@@ -557,7 +519,6 @@ void Sound_set_tempo( struct Hes_Emu* this, int t )
557 this->tempo_ = t; 519 this->tempo_ = t;
558} 520}
559 521
560void fill_buf( struct Hes_Emu* this );
561blargg_err_t Hes_start_track( struct Hes_Emu* this, int track ) 522blargg_err_t Hes_start_track( struct Hes_Emu* this, int track )
562{ 523{
563 clear_track_vars( this ); 524 clear_track_vars( this );
@@ -572,7 +533,7 @@ blargg_err_t Hes_start_track( struct Hes_Emu* this, int track )
572 533
573 Buffer_clear( &this->stereo_buf ); 534 Buffer_clear( &this->stereo_buf );
574 535
575 memset( this->cpu.ram, 0, sizeof this->cpu.ram ); // some HES music relies on zero fill 536 memset( this->ram, 0, sizeof this->ram ); // some HES music relies on zero fill
576 memset( this->sgx, 0, sizeof this->sgx ); 537 memset( this->sgx, 0, sizeof this->sgx );
577 538
578 Apu_reset( &this->apu ); 539 Apu_reset( &this->apu );
@@ -581,12 +542,12 @@ blargg_err_t Hes_start_track( struct Hes_Emu* this, int track )
581 542
582 unsigned i; 543 unsigned i;
583 for ( i = 0; i < sizeof this->header.banks; i++ ) 544 for ( i = 0; i < sizeof this->header.banks; i++ )
584 Cpu_set_mmr( this, i, this->header.banks [i] ); 545 set_mmr( this, i, this->header.banks [i] );
585 Cpu_set_mmr( this, page_count, 0xFF ); // unmapped beyond end of address space 546 set_mmr( this, page_count, 0xFF ); // unmapped beyond end of address space
586 547
587 this->irq.disables = timer_mask | vdp_mask; 548 this->irq.disables = timer_mask | vdp_mask;
588 this->irq.timer = (hes_time_t)future_hes_time; 549 this->irq.timer = future_time;
589 this->irq.vdp = (hes_time_t)future_hes_time; 550 this->irq.vdp = future_time;
590 551
591 this->timer.enabled = false; 552 this->timer.enabled = false;
592 this->timer.raw_load= 0x80; 553 this->timer.raw_load= 0x80;
@@ -598,280 +559,86 @@ blargg_err_t Hes_start_track( struct Hes_Emu* this, int track )
598 this->vdp.control = 0; 559 this->vdp.control = 0;
599 this->vdp.next_vbl = 0; 560 this->vdp.next_vbl = 0;
600 561
601 this->cpu.ram [0x1FF] = (idle_addr - 1) >> 8; 562 this->ram [0x1FF] = (idle_addr - 1) >> 8;
602 this->cpu.ram [0x1FE] = (idle_addr - 1) & 0xFF; 563 this->ram [0x1FE] = (idle_addr - 1) & 0xFF;
603 this->cpu.r.sp = 0xFD; 564 this->cpu.r.sp = 0xFD;
604 this->cpu.r.pc = get_le16( this->header.init_addr ); 565 this->cpu.r.pc = get_le16( this->header.init_addr );
605 this->cpu.r.a = track; 566 this->cpu.r.a = track;
606 567
607 recalc_timer_load( this ); 568 recalc_timer_load( this );
608 this->last_frame_hook = 0;
609 569
610 this->emu_track_ended_ = false; 570 // convert filter times to samples
611 this->track_ended = false; 571 struct setup_t s = this->tfilter;
572 s.max_initial *= this->sample_rate_ * stereo;
573 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
574 s.lookahead = 1;
575 #endif
576 track_setup( &this->track_filter, &s );
612 577
613 if ( !this->ignore_silence ) 578 return track_start( &this->track_filter );
614 {
615 // play until non-silence or end of track
616 long end;
617 for ( end =this-> max_initial_silence * stereo * this->sample_rate_; this->emu_time < end; )
618 {
619 fill_buf( this );
620 if ( this->buf_remain | (int) this->emu_track_ended_ )
621 break;
622 }
623
624 this->emu_time = this->buf_remain;
625 this->out_time = 0;
626 this->silence_time = 0;
627 this->silence_count = 0;
628 }
629 /* return track_ended() ? warning() : 0; */
630 return 0;
631} 579}
632 580
633// Tell/Seek 581// Tell/Seek
634 582
635static blargg_long msec_to_samples( blargg_long msec, long sample_rate ) 583static int msec_to_samples( int msec, int sample_rate )
636{ 584{
637 blargg_long sec = msec / 1000; 585 int sec = msec / 1000;
638 msec -= sec * 1000; 586 msec -= sec * 1000;
639 return (sec * sample_rate + msec * sample_rate / 1000) * stereo; 587 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
640} 588}
641 589
642long Track_tell( struct Hes_Emu* this ) 590int Track_tell( struct Hes_Emu* this )
643{ 591{
644 blargg_long rate = this->sample_rate_ * stereo; 592 int rate = this->sample_rate_ * stereo;
645 blargg_long sec = this->out_time / rate; 593 int sec = track_sample_count( &this->track_filter ) / rate;
646 return sec * 1000 + (this->out_time - sec * rate) * 1000 / rate; 594 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
647} 595}
648 596
649blargg_err_t Track_seek( struct Hes_Emu* this, long msec ) 597blargg_err_t Track_seek( struct Hes_Emu* this, int msec )
650{ 598{
651 blargg_long time = msec_to_samples( msec, this->sample_rate_ ); 599 int time = msec_to_samples( msec, this->sample_rate_ );
652 if ( time < this->out_time ) 600 if ( time < track_sample_count( &this->track_filter ) )
653 RETURN_ERR( Hes_start_track( this, this->current_track_ ) ); 601 RETURN_ERR( Hes_start_track( this, this->current_track_ ) );
654 return Track_skip( this, time - this->out_time ); 602 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
655} 603}
656 604
657blargg_err_t skip_( struct Hes_Emu* this, long count ); 605blargg_err_t skip_( void* emu, int count )
658blargg_err_t skip_( struct Hes_Emu* this, long count )
659{ 606{
607 struct Hes_Emu* this = (struct Hes_Emu*) emu;
608
660 // for long skip, mute sound 609 // for long skip, mute sound
661 const long threshold = 30000; 610 const int threshold = 32768;
662 if ( count > threshold ) 611 if ( count > threshold )
663 { 612 {
664 int saved_mute = this->mute_mask_; 613 int saved_mute = this->mute_mask_;
665 Sound_mute_voices( this, ~0 ); 614 Sound_mute_voices( this, ~0 );
666
667 while ( count > threshold / 2 && !this->emu_track_ended_ )
668 {
669 RETURN_ERR( play_( this, buf_size, this->buf ) );
670 count -= buf_size;
671 }
672
673 Sound_mute_voices( this, saved_mute );
674 }
675
676 while ( count && !this->emu_track_ended_ )
677 {
678 long n = buf_size;
679 if ( n > count )
680 n = count;
681 count -= n;
682 RETURN_ERR( play_( this, n, this->buf ) );
683 }
684 return 0;
685}
686 615
687blargg_err_t Track_skip( struct Hes_Emu* this, long count ) 616 int n = count - threshold/2;
688{ 617 n &= ~(2048-1); // round to multiple of 2048
689 require( this->current_track_ >= 0 ); // start_track() must have been called already
690 this->out_time += count;
691
692 // remove from silence and buf first
693 {
694 long n = min( count, this->silence_count );
695 this->silence_count -= n;
696 count -= n;
697
698 n = min( count, this->buf_remain );
699 this->buf_remain -= n;
700 count -= n; 618 count -= n;
701 } 619 RETURN_ERR( skippy_( &this->track_filter, n ) );
702
703 if ( count && !this->emu_track_ended_ )
704 {
705 this->emu_time += count;
706
707 // End track if error
708 if ( skip_( this, count ) )
709 this->emu_track_ended_ = true;
710 }
711
712 if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended
713 this->track_ended |= this->emu_track_ended_;
714
715 return 0;
716}
717 620
718 621 Sound_mute_voices( this, saved_mute );
719
720// Fading
721
722void Track_set_fade( struct Hes_Emu* this, long start_msec, long length_msec )
723{
724 this->fade_step = this->sample_rate_ * length_msec / (fade_block_size * fade_shift * 1000 / stereo);
725 this->fade_start = msec_to_samples( start_msec, this->sample_rate_ );
726}
727
728// unit / pow( 2.0, (double) x / step )
729static int int_log( blargg_long x, int step, int unit );
730static int int_log( blargg_long x, int step, int unit )
731{
732 int shift = x / step;
733 int fraction = (x - shift * step) * unit / step;
734 return ((unit - fraction) + (fraction >> 1)) >> shift;
735}
736
737void handle_fade( struct Hes_Emu* this, long out_count, sample_t* out );
738void handle_fade( struct Hes_Emu* this, long out_count, sample_t* out )
739{
740 int i;
741 for ( i = 0; i < out_count; i += fade_block_size )
742 {
743 int const shift = 14;
744 int const unit = 1 << shift;
745 int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size,
746 this->fade_step, unit );
747 if ( gain < (unit >> fade_shift) )
748 this->track_ended = this->emu_track_ended_ = true;
749
750 sample_t* io = &out [i];
751 int count;
752 for ( count = min( fade_block_size, out_count - i ); count; --count )
753 {
754 *io = (sample_t) ((*io * gain) >> shift);
755 ++io;
756 }
757 } 622 }
758}
759
760// Silence detection
761 623
762void emu_play( struct Hes_Emu* this, long count, sample_t* out ); 624 return skippy_( &this->track_filter, count );
763void emu_play( struct Hes_Emu* this, long count, sample_t* out )
764{
765 check( current_track_ >= 0 );
766 this->emu_time += count;
767 if ( this->current_track_ >= 0 && !this->emu_track_ended_ ) {
768
769 // End track if error
770 if ( play_( this, count, out ) )
771 this->emu_track_ended_ = true;
772 }
773 else
774 memset( out, 0, count * sizeof *out );
775} 625}
776 626
777// number of consecutive silent samples at end 627blargg_err_t Track_skip( struct Hes_Emu* this, int count )
778static long count_silence( sample_t* begin, long size );
779static long count_silence( sample_t* begin, long size )
780{ 628{
781 sample_t first = *begin; 629 require( this->current_track_ >= 0 ); // start_track() must have been called already
782 *begin = silence_threshold; // sentinel 630 return track_skip( &this->track_filter, count );
783 sample_t* p = begin + size;
784 while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
785 *begin = first;
786 return size - (p - begin);
787} 631}
788 632
789// fill internal buffer and check it for silence 633void Track_set_fade( struct Hes_Emu* this, int start_msec, int length_msec )
790void fill_buf( struct Hes_Emu* this )
791{ 634{
792 assert( !this->buf_remain ); 635 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate_ ),
793 if ( !this->emu_track_ended_ ) 636 length_msec * this->sample_rate_ / (1000 / stereo) );
794 {
795 emu_play( this, buf_size, this->buf );
796 long silence = count_silence( this->buf, buf_size );
797 if ( silence < buf_size )
798 {
799 this->silence_time = this->emu_time - silence;
800 this->buf_remain = buf_size;
801 return;
802 }
803 }
804 this->silence_count += buf_size;
805} 637}
806 638
807blargg_err_t Hes_play( struct Hes_Emu* this, long out_count, sample_t* out ) 639blargg_err_t Hes_play( struct Hes_Emu* this, int out_count, sample_t* out )
808{ 640{
809 if ( this->track_ended ) 641 require( this->current_track_ >= 0 );
810 { 642 require( out_count % stereo == 0 );
811 memset( out, 0, out_count * sizeof *out ); 643 return track_play( &this->track_filter, out_count, out );
812 }
813 else
814 {
815 require( this->current_track_ >= 0 );
816 require( out_count % stereo == 0 );
817
818 assert( this->emu_time >= this->out_time );
819
820 // prints nifty graph of how far ahead we are when searching for silence
821 //dprintf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" );
822
823 long pos = 0;
824 if ( this->silence_count )
825 {
826 // during a run of silence, run emulator at >=2x speed so it gets ahead
827 long ahead_time = this->silence_lookahead * (this->out_time + out_count - this->silence_time) + this->silence_time;
828 while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) )
829 fill_buf( this );
830
831 // fill with silence
832 pos = min( this->silence_count, out_count );
833 memset( out, 0, pos * sizeof *out );
834 this->silence_count -= pos;
835
836 if ( this->emu_time - this->silence_time > silence_max * stereo * this->sample_rate_ )
837 {
838 this->track_ended = this->emu_track_ended_ = true;
839 this->silence_count = 0;
840 this->buf_remain = 0;
841 }
842 }
843
844 if ( this->buf_remain )
845 {
846 // empty silence buf
847 long n = min( this->buf_remain, out_count - pos );
848 memcpy( &out [pos], this->buf + (buf_size - this->buf_remain), n * sizeof *out );
849 this->buf_remain -= n;
850 pos += n;
851 }
852
853 // generate remaining samples normally
854 long remain = out_count - pos;
855 if ( remain )
856 {
857 emu_play( this, remain, out + pos );
858 this->track_ended |= this->emu_track_ended_;
859
860 if ( !this->ignore_silence || this->out_time > this->fade_start )
861 {
862 // check end for a new run of silence
863 long silence = count_silence( out + pos, remain );
864 if ( silence < remain )
865 this->silence_time = this->emu_time - silence;
866
867 if ( this->emu_time - this->silence_time >= buf_size )
868 fill_buf( this ); // cause silence detection on next play()
869 }
870 }
871
872 if ( this->out_time > this->fade_start )
873 handle_fade( this, out_count, out );
874 }
875 this->out_time += out_count;
876 return 0;
877} 644}
diff --git a/apps/codecs/libgme/hes_emu.h b/apps/codecs/libgme/hes_emu.h
index 0dcd29a9c6..a1dd048498 100644
--- a/apps/codecs/libgme/hes_emu.h
+++ b/apps/codecs/libgme/hes_emu.h
@@ -12,88 +12,67 @@
12#include "hes_apu_adpcm.h" 12#include "hes_apu_adpcm.h"
13#include "hes_cpu.h" 13#include "hes_cpu.h"
14#include "m3u_playlist.h" 14#include "m3u_playlist.h"
15 15#include "track_filter.h"
16typedef short sample_t;
17
18enum { buf_size = 2048 };
19 16
20// HES file header 17// HES file header
18enum { info_offset = 0x20 };
21enum { header_size = 0x20 }; 19enum { header_size = 0x20 };
22struct header_t 20struct header_t
23{ 21{
24 byte tag [4]; 22 byte tag [4];
25 byte vers; 23 byte vers;
26 byte first_track; 24 byte first_track;
27 byte init_addr [2]; 25 byte init_addr [2];
28 byte banks [8]; 26 byte banks [8];
29 byte data_tag [4]; 27 byte data_tag [4];
30 byte size [4]; 28 byte size [4];
31 byte addr [4]; 29 byte addr [4];
32 byte unused [4]; 30 byte unused [4];
33}; 31};
34 32
35 33
36struct timer_t { 34struct timer_t {
37 hes_time_t last_time; 35 hes_time_t last_time;
38 blargg_long count; 36 int count;
39 blargg_long load; 37 int load;
40 int raw_load; 38 int raw_load;
41 byte enabled; 39 byte enabled;
42 byte fired; 40 byte fired;
43}; 41};
44 42
45struct vdp_t { 43struct vdp_t {
46 hes_time_t next_vbl; 44 hes_time_t next_vbl;
47 byte latch; 45 byte latch;
48 byte control; 46 byte control;
49}; 47};
50 48
51struct irq_t { 49struct irq_t {
52 hes_time_t timer; 50 hes_time_t timer;
53 hes_time_t vdp; 51 hes_time_t vdp;
54 byte disables; 52 byte disables;
55}; 53};
56 54
57
58struct Hes_Emu { 55struct Hes_Emu {
59 hes_time_t play_period; 56 hes_time_t play_period;
60 hes_time_t last_frame_hook;
61 int timer_base; 57 int timer_base;
62 58
63 struct timer_t timer; 59 struct timer_t timer;
64 struct vdp_t vdp; 60 struct vdp_t vdp;
65 struct irq_t irq; 61 struct irq_t irq;
66 62
67 // Sound 63 // Sound
68 long clock_rate_; 64 int clock_rate_;
69 long sample_rate_; 65 int sample_rate_;
70 unsigned buf_changed_count; 66 unsigned buf_changed_count;
71 int voice_count_; 67 int voice_count_;
68 int const* voice_types_;
69 int mute_mask_;
72 int tempo_; 70 int tempo_;
73 int gain_; 71 int gain_;
74 72
75 // track-specific 73 // track-specific
76 byte track_count; 74 byte track_count;
77 volatile bool track_ended;
78 int current_track_; 75 int current_track_;
79 blargg_long out_time; // number of samples played since start of track
80 blargg_long emu_time; // number of samples emulator has generated since start of track
81 bool emu_track_ended_; // emulator has reached end of track
82
83 // fading
84 blargg_long fade_start;
85 int fade_step;
86
87 // silence detection
88 // Disable automatic end-of-track detection and skipping of silence at beginning
89 bool ignore_silence;
90
91 int max_initial_silence;
92 int mute_mask_;
93 int silence_lookahead; // speed to run emulator when looking ahead for silence
94 long silence_time; // number of samples where most recent silence began
95 long silence_count; // number of samples of silence to play before using buf
96 long buf_remain; // number of samples left in silence buffer
97 76
98 // Larger files at the end 77 // Larger files at the end
99 // Header for currently loaded file 78 // Header for currently loaded file
@@ -102,19 +81,22 @@ struct Hes_Emu {
102 // M3u Playlist 81 // M3u Playlist
103 struct M3u_Playlist m3u; 82 struct M3u_Playlist m3u;
104 83
84 struct setup_t tfilter;
85 struct Track_Filter track_filter;
86
105 // Hes Cpu 87 // Hes Cpu
106 byte* write_pages [page_count + 1]; // 0 if unmapped or I/O space
107 struct Hes_Cpu cpu; 88 struct Hes_Cpu cpu;
89 struct Rom_Data rom;
108 90
109 struct Hes_Apu apu; 91 struct Hes_Apu apu;
110 struct Hes_Apu_Adpcm adpcm; 92 struct Hes_Apu_Adpcm adpcm;
111 93
112 struct Stereo_Buffer stereo_buf; 94 struct Multi_Buffer stereo_buf;
113 sample_t buf [buf_size];
114 95
115 // rom & ram 96 // rom & ram
116 struct Rom_Data rom; 97 byte* write_pages [page_count + 1]; // 0 if unmapped or I/O space
117 byte sgx [3 * page_size + cpu_padding]; 98 byte ram [page_size];
99 byte sgx [3 * page_size + cpu_padding];
118}; 100};
119 101
120 102
@@ -126,36 +108,48 @@ void Hes_init( struct Hes_Emu* this );
126void Hes_stop( struct Hes_Emu* this ); 108void Hes_stop( struct Hes_Emu* this );
127 109
128// Loads a file from memory 110// Loads a file from memory
129blargg_err_t Hes_load( struct Hes_Emu* this, void* data, long size ); 111blargg_err_t Hes_load_mem( struct Hes_Emu* this, void* data, long size );
130 112
131// Set output sample rate. Must be called only once before loading file. 113// Set output sample rate. Must be called only once before loading file.
132blargg_err_t Hes_set_sample_rate( struct Hes_Emu* this, long sample_rate ); 114blargg_err_t Hes_set_sample_rate( struct Hes_Emu* this, int sample_rate );
133 115
134// Start a track, where 0 is the first track. Also clears warning string. 116// Start a track, where 0 is the first track. Also clears warning string.
135blargg_err_t Hes_start_track( struct Hes_Emu* this, int ); 117blargg_err_t Hes_start_track( struct Hes_Emu* this, int );
136 118
137// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation 119// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
138// errors set warning string, and major errors also end track. 120// errors set warning string, and major errors also end track.
139blargg_err_t Hes_play( struct Hes_Emu* this, long count, sample_t* buf ); 121blargg_err_t Hes_play( struct Hes_Emu* this, int count, sample_t* buf );
140 122
141// Track status/control 123// Track status/control
142// Number of milliseconds (1000 msec = 1 second) played since ning of track 124// Number of milliseconds (1000 msec = 1 second) played since ning of track
143long Track_tell( struct Hes_Emu* this ); 125int Track_tell( struct Hes_Emu* this );
144 126
145// Seek to new time in track. Seeking backwards or far forward can take a while. 127// Seek to new time in track. Seeking backwards or far forward can take a while.
146blargg_err_t Track_seek( struct Hes_Emu* this, long msec ); 128blargg_err_t Track_seek( struct Hes_Emu* this, int msec );
147 129
148// Skip n samples 130// Skip n samples
149blargg_err_t Track_skip( struct Hes_Emu* this, long n ); 131blargg_err_t Track_skip( struct Hes_Emu* this, int n );
150 132
151// Set start time and length of track fade out. Once fade ends track_ended() returns 133// Set start time and length of track fade out. Once fade ends track_ended() returns
152// true. Fade time can be changed while track is playing. 134// true. Fade time can be changed while track is playing.
153void Track_set_fade( struct Hes_Emu* this, long start_msec, long length_msec ); 135void Track_set_fade( struct Hes_Emu* this, int start_msec, int length_msec );
136
137// True if a track has reached its end
138static inline bool Track_ended( struct Hes_Emu* this )
139{
140 return track_ended( &this->track_filter );
141}
142
143// Disables automatic end-of-track detection and skipping of silence at beginning
144static inline void Track_ignore_silence( struct Hes_Emu* this, bool disable )
145{
146 this->track_filter.silence_ignored_ = disable;
147}
154 148
155// Get track length in milliseconds 149// Get track length in milliseconds
156static inline long Track_get_length( struct Hes_Emu* this, int n ) 150static inline int Track_get_length( struct Hes_Emu* this, int n )
157{ 151{
158 long length = 120 * 1000; /* 2 minutes */ 152 int length = 120 * 1000; /* 2 minutes */
159 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) { 153 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
160 struct entry_t* entry = &this->m3u.entries [n]; 154 struct entry_t* entry = &this->m3u.entries [n];
161 length = entry->length; 155 length = entry->length;
@@ -185,45 +179,17 @@ static inline void Sound_set_gain( struct Hes_Emu* this, int g )
185 this->gain_ = g; 179 this->gain_ = g;
186} 180}
187 181
188
189// Emulation (You shouldn't touch these) 182// Emulation (You shouldn't touch these)
190 183
191int Cpu_read( struct Hes_Emu* this, hes_addr_t ); 184void irq_changed( struct Hes_Emu* this );
192void Cpu_write( struct Hes_Emu* this, hes_addr_t, int ); 185void run_until( struct Hes_Emu* this, hes_time_t );
193void Cpu_write_vdp( struct Hes_Emu* this, int addr, int data ); 186bool run_cpu( struct Hes_Emu* this, hes_time_t end );
194int Cpu_done( struct Hes_Emu* this ); 187int read_mem_( struct Hes_Emu* this, hes_addr_t );
195 188int read_mem( struct Hes_Emu* this, hes_addr_t );
196int Emu_cpu_read( struct Hes_Emu* this, hes_addr_t ); 189void write_mem_( struct Hes_Emu* this, hes_addr_t, int data );
197void Emu_cpu_write( struct Hes_Emu* this, hes_addr_t, int data ); 190void write_mem( struct Hes_Emu* this, hes_addr_t, int );
198 191void write_vdp( struct Hes_Emu* this, int addr, int data );
199static inline byte const* Emu_cpu_set_mmr( struct Hes_Emu* this, int page, int bank ) 192void set_mmr( struct Hes_Emu* this, int reg, int bank );
200{ 193int cpu_done( struct Hes_Emu* this );
201 this->write_pages [page] = 0;
202 if ( bank < 0x80 )
203 return Rom_at_addr( &this->rom, bank * (blargg_long) page_size );
204
205 byte* data = 0;
206 switch ( bank )
207 {
208 case 0xF8:
209 data = this->cpu.ram;
210 break;
211
212 case 0xF9:
213 case 0xFA:
214 case 0xFB:
215 data = &this->sgx [(bank - 0xF9) * page_size];
216 break;
217
218 default:
219 if ( bank != 0xFF ) {
220 dprintf( "Unmapped bank $%02X\n", bank );
221 }
222 return this->rom.unmapped;
223 }
224
225 this->write_pages [page] = data;
226 return data;
227}
228 194
229#endif 195#endif
diff --git a/apps/codecs/libgme/kss_emu.c b/apps/codecs/libgme/kss_emu.c
index 060a5b74b0..ba80ef613e 100644
--- a/apps/codecs/libgme/kss_emu.c
+++ b/apps/codecs/libgme/kss_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 "kss_emu.h" 3#include "kss_emu.h"
4 4
@@ -17,29 +17,14 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
17 17
18#include "blargg_source.h" 18#include "blargg_source.h"
19 19
20long const clock_rate = 3579545; 20int const clock_rate = 3579545;
21 21
22const char gme_wrong_file_type [] = "Wrong file type for this emulator"; 22const char gme_wrong_file_type [] = "Wrong file type for this emulator";
23 23
24int const stereo = 2; // number of channels for stereo
25int const silence_max = 6; // seconds
26int const silence_threshold = 0x10;
27long const fade_block_size = 512;
28int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
29
30static void clear_track_vars( struct Kss_Emu* this ) 24static void clear_track_vars( struct Kss_Emu* this )
31{ 25{
32 this->current_track = -1; 26 this->current_track = -1;
33 this->out_time = 0; 27 track_stop( &this->track_filter );
34 this->emu_time = 0;
35 this->emu_track_ended_ = true;
36 this->track_ended = true;
37 this->fade_start = INT_MAX / 2 + 1;
38 this->fade_step = 1;
39 this->silence_time = 0;
40 this->silence_count = 0;
41 this->buf_remain = 0;
42 // warning(); // clear warning
43} 28}
44 29
45static blargg_err_t init_opl_apu( enum opl_type_t type, struct Opl_Apu* out ) 30static blargg_err_t init_opl_apu( enum opl_type_t type, struct Opl_Apu* out )
@@ -58,17 +43,15 @@ void Kss_init( struct Kss_Emu* this )
58 this->chip_flags = 0; 43 this->chip_flags = 0;
59 44
60 // defaults 45 // defaults
61 this->max_initial_silence = 2; 46 this->tfilter = *track_get_setup( &this->track_filter );
62 this->silence_lookahead = 6; 47 this->tfilter.max_initial = 2;
63 this->ignore_silence = false; 48 this->tfilter.lookahead = 6;
64 49 this->track_filter.silence_ignored_ = false;
65 this->voice_count = 0;
66 clear_track_vars( this );
67 50
68 memset( this->unmapped_read, 0xFF, sizeof this->unmapped_read ); 51 memset( this->unmapped_read, 0xFF, sizeof this->unmapped_read );
69 52
70 // Init all stuff 53 // Init all stuff
71 Buffer_init( &this->stereo_buffer ); 54 Buffer_init( &this->stereo_buf );
72 55
73 Z80_init( &this->cpu ); 56 Z80_init( &this->cpu );
74 Rom_init( &this->rom, page_size ); 57 Rom_init( &this->rom, page_size );
@@ -83,6 +66,10 @@ void Kss_init( struct Kss_Emu* this )
83 init_opl_apu( type_msxmusic, &this->msx.music ); 66 init_opl_apu( type_msxmusic, &this->msx.music );
84 init_opl_apu( type_msxaudio, &this->msx.audio ); 67 init_opl_apu( type_msxaudio, &this->msx.audio );
85#endif 68#endif
69
70 this->voice_count = 0;
71 this->voice_types = 0;
72 clear_track_vars( this );
86} 73}
87 74
88// Track info 75// Track info
@@ -96,7 +83,7 @@ static blargg_err_t check_kss_header( void const* header )
96 83
97// Setup 84// Setup
98 85
99static void update_gain( struct Kss_Emu* this ) 86static void update_gain_( struct Kss_Emu* this )
100{ 87{
101 int g = this->gain; 88 int g = this->gain;
102 if ( msx_music_enabled( this ) || msx_audio_enabled( this ) 89 if ( msx_music_enabled( this ) || msx_audio_enabled( this )
@@ -118,6 +105,15 @@ static void update_gain( struct Kss_Emu* this )
118 if ( msx_audio_enabled( this ) ) Opl_volume( &this->msx.audio, g ); 105 if ( msx_audio_enabled( this ) ) Opl_volume( &this->msx.audio, g );
119} 106}
120 107
108static void update_gain( struct Kss_Emu* this )
109{
110 if ( this->scc_accessed )
111 {
112 /* dprintf( "SCC accessed\n" ); */
113 update_gain_( this );
114 }
115}
116
121blargg_err_t Kss_load_mem( struct Kss_Emu* this, const void* data, long size ) 117blargg_err_t Kss_load_mem( struct Kss_Emu* this, const void* data, long size )
122{ 118{
123 /* warning( core.warning() ); */ 119 /* warning( core.warning() ); */
@@ -176,6 +172,10 @@ blargg_err_t Kss_load_mem( struct Kss_Emu* this, const void* data, long size )
176 172
177 // sms.psg 173 // sms.psg
178 this->voice_count = sms_osc_count; 174 this->voice_count = sms_osc_count;
175 static int const types [sms_osc_count + opl_osc_count] = {
176 wave_type+1, wave_type+3, wave_type+2, mixed_type+1, wave_type+0
177 };
178 this->voice_types = types;
179 this->chip_flags |= sms_psg_flag; 179 this->chip_flags |= sms_psg_flag;
180 180
181 // sms.fm 181 // sms.fm
@@ -191,6 +191,10 @@ blargg_err_t Kss_load_mem( struct Kss_Emu* this, const void* data, long size )
191 191
192 // msx.psg 192 // msx.psg
193 this->voice_count = ay_osc_count; 193 this->voice_count = ay_osc_count;
194 static int const types [ay_osc_count + opl_osc_count] = {
195 wave_type+1, wave_type+3, wave_type+2, wave_type+0
196 };
197 this->voice_types = types;
194 this->chip_flags |= msx_psg_flag; 198 this->chip_flags |= msx_psg_flag;
195 199
196 /* if ( this->header.device_flags & 0x10 ) 200 /* if ( this->header.device_flags & 0x10 )
@@ -220,21 +224,27 @@ blargg_err_t Kss_load_mem( struct Kss_Emu* this, const void* data, long size )
220 // msx.scc 224 // msx.scc
221 this->chip_flags |= msx_scc_flag; 225 this->chip_flags |= msx_scc_flag;
222 this->voice_count = ay_osc_count + scc_osc_count; 226 this->voice_count = ay_osc_count + scc_osc_count;
227 static int const types [ay_osc_count + scc_osc_count] = {
228 wave_type+1, wave_type+3, wave_type+2,
229 wave_type+0, wave_type+4, wave_type+5, wave_type+6, wave_type+7,
230 };
231 this->voice_types = types;
223 } 232 }
224 } 233 }
225 234
226 this->silence_lookahead = 6; 235 this->tfilter.lookahead = 6;
227 if ( sms_fm_enabled( this ) || msx_music_enabled( this ) || msx_audio_enabled( this ) ) 236 if ( sms_fm_enabled( this ) || msx_music_enabled( this ) || msx_audio_enabled( this ) )
228 { 237 {
229 if ( !Opl_supported() ) 238 if ( !Opl_supported() )
230 ; /* warning( "FM sound not supported" ); */ 239 ; /* warning( "FM sound not supported" ); */
231 else 240 else
232 this->silence_lookahead = 3; // Opl_Apu is really slow 241 this->tfilter.lookahead = 3; // Opl_Apu is really slow
233 } 242 }
234 243
235 this->clock_rate_ = clock_rate; 244 this->clock_rate_ = clock_rate;
236 Buffer_clock_rate( &this->stereo_buffer, clock_rate ); 245 Buffer_clock_rate( &this->stereo_buf, clock_rate );
237 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buffer ); 246 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
247 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
238 248
239 Sound_set_tempo( this, this->tempo ); 249 Sound_set_tempo( this, this->tempo );
240 Sound_mute_voices( this, this->mute_mask_ ); 250 Sound_mute_voices( this, this->mute_mask_ );
@@ -265,8 +275,8 @@ static void set_voice( struct Kss_Emu* this, int i, struct Blip_Buffer* center,
265 } 275 }
266 276
267 if ( msx_scc_enabled( this ) && i < scc_osc_count ) Scc_set_output( &this->msx.scc, i, center ); 277 if ( msx_scc_enabled( this ) && i < scc_osc_count ) Scc_set_output( &this->msx.scc, i, center );
268 if ( msx_music_enabled( this ) && i < opl_osc_count ) Opl_set_output( &this->msx.music, center ); 278 if ( msx_music_enabled( this ) && i < opl_osc_count ) Opl_set_output( &this->msx.music, center );
269 if ( msx_audio_enabled( this ) && i < opl_osc_count ) Opl_set_output( &this->msx.audio, center ); 279 if ( msx_audio_enabled( this ) && i < opl_osc_count ) Opl_set_output( &this->msx.audio, center );
270 } 280 }
271} 281}
272 282
@@ -465,15 +475,17 @@ blargg_err_t end_frame( struct Kss_Emu* this, kss_time_t end )
465 475
466// MUSIC 476// MUSIC
467 477
468 478blargg_err_t Kss_set_sample_rate( struct Kss_Emu* this, int rate )
469blargg_err_t Kss_set_sample_rate( struct Kss_Emu* this, long rate )
470{ 479{
471 require( !this->sample_rate ); // sample rate can't be changed once set 480 require( !this->sample_rate ); // sample rate can't be changed once set
472 RETURN_ERR( Buffer_set_sample_rate( &this->stereo_buffer, rate, 1000 / 20 ) ); 481 RETURN_ERR( Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 ) );
473 482
474 // Set bass frequency 483 // Set bass frequency
475 Buffer_bass_freq( &this->stereo_buffer, 180 ); 484 Buffer_bass_freq( &this->stereo_buf, 180 );
485
476 this->sample_rate = rate; 486 this->sample_rate = rate;
487 RETURN_ERR( track_init( &this->track_filter, this ) );
488 this->tfilter.max_silence = 6 * stereo * this->sample_rate;
477 return 0; 489 return 0;
478} 490}
479 491
@@ -501,7 +513,7 @@ void Sound_mute_voices( struct Kss_Emu* this, int mask )
501 } 513 }
502 else 514 else
503 { 515 {
504 struct channel_t ch = Buffer_channel( &this->stereo_buffer ); 516 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
505 assert( (ch.center && ch.left && ch.right) || 517 assert( (ch.center && ch.left && ch.right) ||
506 (!ch.center && !ch.left && !ch.right) ); // all or nothing 518 (!ch.center && !ch.left && !ch.right) ); // all or nothing
507 set_voice( this, i, ch.center, ch.left, ch.right ); 519 set_voice( this, i, ch.center, ch.left, ch.right );
@@ -523,7 +535,6 @@ void Sound_set_tempo( struct Kss_Emu* this, int t )
523 this->play_period = (blip_time_t) ((period * FP_ONE_TEMPO) / t); 535 this->play_period = (blip_time_t) ((period * FP_ONE_TEMPO) / t);
524} 536}
525 537
526void fill_buf( struct Kss_Emu* this );
527blargg_err_t Kss_start_track( struct Kss_Emu* this, int track ) 538blargg_err_t Kss_start_track( struct Kss_Emu* this, int track )
528{ 539{
529 clear_track_vars( this ); 540 clear_track_vars( this );
@@ -536,7 +547,7 @@ blargg_err_t Kss_start_track( struct Kss_Emu* this, int track )
536 547
537 this->current_track = track; 548 this->current_track = track;
538 549
539 Buffer_clear( &this->stereo_buffer ); 550 Buffer_clear( &this->stereo_buf );
540 551
541 if ( sms_psg_enabled( this ) ) Sms_apu_reset( &this->sms.psg, 0, 0 ); 552 if ( sms_psg_enabled( this ) ) Sms_apu_reset( &this->sms.psg, 0, 0 );
542 if ( sms_fm_enabled( this ) ) Opl_reset( &this->sms.fm ); 553 if ( sms_fm_enabled( this ) ) Opl_reset( &this->sms.fm );
@@ -546,7 +557,7 @@ blargg_err_t Kss_start_track( struct Kss_Emu* this, int track )
546 if ( msx_audio_enabled( this ) ) Opl_reset( &this->msx.audio ); 557 if ( msx_audio_enabled( this ) ) Opl_reset( &this->msx.audio );
547 558
548 this->scc_accessed = false; 559 this->scc_accessed = false;
549 update_gain( this ); 560 update_gain_( this );
550 561
551 memset( this->ram, 0xC9, 0x4000 ); 562 memset( this->ram, 0xC9, 0x4000 );
552 memset( this->ram + 0x4000, 0, sizeof this->ram - 0x4000 ); 563 memset( this->ram + 0x4000, 0, sizeof this->ram - 0x4000 );
@@ -598,286 +609,106 @@ blargg_err_t Kss_start_track( struct Kss_Emu* this, int track )
598 this->gain_updated = false; 609 this->gain_updated = false;
599 jsr( this, this->header.init_addr ); 610 jsr( this, this->header.init_addr );
600 611
601 this->emu_track_ended_ = false; 612 // convert filter times to samples
602 this->track_ended = false; 613 struct setup_t s = this->tfilter;
614 s.max_initial *= this->sample_rate * stereo;
615 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
616 s.lookahead = 1;
617 #endif
618 track_setup( &this->track_filter, &s );
603 619
604 if ( !this->ignore_silence ) 620 return track_start( &this->track_filter );
605 {
606 // play until non-silence or end of track
607 long end;
608 for ( end = this->max_initial_silence * stereo * this->sample_rate; this->emu_time < end; )
609 {
610 fill_buf( this );
611 if ( this->buf_remain | (int) this->emu_track_ended_ )
612 break;
613 }
614
615 this->emu_time = this->buf_remain;
616 this->out_time = 0;
617 this->silence_time = 0;
618 this->silence_count = 0;
619 }
620 /* return track_ended() ? warning() : 0; */
621 return 0;
622} 621}
623 622
624// Tell/Seek 623// Tell/Seek
625 624
626static blargg_long msec_to_samples( blargg_long msec, long sample_rate ) 625static int msec_to_samples( int msec, int sample_rate )
627{ 626{
628 blargg_long sec = msec / 1000; 627 int sec = msec / 1000;
629 msec -= sec * 1000; 628 msec -= sec * 1000;
630 return (sec * sample_rate + msec * sample_rate / 1000) * stereo; 629 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
631} 630}
632 631
633long Track_tell( struct Kss_Emu* this ) 632int Track_tell( struct Kss_Emu* this )
634{ 633{
635 blargg_long rate = this->sample_rate * stereo; 634 int rate = this->sample_rate * stereo;
636 blargg_long sec = this->out_time / rate; 635 int sec = track_sample_count( &this->track_filter ) / rate;
637 return sec * 1000 + (this->out_time - sec * rate) * 1000 / rate; 636 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
638} 637}
639 638
640blargg_err_t Track_seek( struct Kss_Emu* this, long msec ) 639blargg_err_t Track_seek( struct Kss_Emu* this, int msec )
641{ 640{
642 blargg_long time = msec_to_samples( msec, this->sample_rate ); 641 int time = msec_to_samples( msec, this->sample_rate );
643 if ( time < this->out_time ) 642 if ( time < track_sample_count( &this->track_filter ) )
644 RETURN_ERR( Kss_start_track( this, this->current_track ) ); 643 RETURN_ERR( Kss_start_track( this, this->current_track ) );
645 return Track_skip( this, time - this->out_time ); 644 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
646} 645}
647 646
648blargg_err_t play_( struct Kss_Emu* this, long count, sample_t* out ); 647blargg_err_t skip_( void *emu, int count )
649static blargg_err_t skip_( struct Kss_Emu* this, long count )
650{ 648{
649 struct Kss_Emu* this = (struct Kss_Emu*) emu;
650
651 // for long skip, mute sound 651 // for long skip, mute sound
652 const long threshold = 30000; 652 const int threshold = 32768;
653 if ( count > threshold ) 653 if ( count > threshold )
654 { 654 {
655 int saved_mute = this->mute_mask_; 655 int saved_mute = this->mute_mask_;
656 Sound_mute_voices( this, ~0 ); 656 Sound_mute_voices( this, ~0 );
657
658 while ( count > threshold / 2 && !this->emu_track_ended_ )
659 {
660 RETURN_ERR( play_( this, buf_size, this->buf ) );
661 count -= buf_size;
662 }
663
664 Sound_mute_voices( this, saved_mute );
665 }
666
667 while ( count && !this->emu_track_ended_ )
668 {
669 long n = buf_size;
670 if ( n > count )
671 n = count;
672 count -= n;
673 RETURN_ERR( play_( this, n, this->buf ) );
674 }
675 return 0;
676}
677 657
678blargg_err_t Track_skip( struct Kss_Emu* this, long count ) 658 int n = count - threshold/2;
679{ 659 n &= ~(2048-1); // round to multiple of 2048
680 require( this->current_track >= 0 ); // start_track() must have been called already
681 this->out_time += count;
682
683 // remove from silence and buf first
684 {
685 long n = min( count, this->silence_count );
686 this->silence_count -= n;
687 count -= n;
688
689 n = min( count, this->buf_remain );
690 this->buf_remain -= n;
691 count -= n; 660 count -= n;
692 } 661 RETURN_ERR( skippy_( &this->track_filter, n ) );
693
694 if ( count && !this->emu_track_ended_ )
695 {
696 this->emu_time += count;
697 if ( skip_( this, count ) )
698 this->emu_track_ended_ = true;
699 }
700
701 if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended
702 this->track_ended |= this->emu_track_ended_;
703
704 return 0;
705}
706
707// Fading
708 662
709void Track_set_fade( struct Kss_Emu* this, long start_msec, long length_msec ) 663 Sound_mute_voices( this, saved_mute );
710{
711 this->fade_step = this->sample_rate * length_msec / (fade_block_size * fade_shift * 1000 / stereo);
712 this->fade_start = msec_to_samples( start_msec, this->sample_rate );
713}
714
715// unit / pow( 2.0, (double) x / step )
716static int int_log( blargg_long x, int step, int unit )
717{
718 int shift = x / step;
719 int fraction = (x - shift * step) * unit / step;
720 return ((unit - fraction) + (fraction >> 1)) >> shift;
721}
722
723static void handle_fade( struct Kss_Emu *this, long out_count, sample_t* out )
724{
725 int i;
726 for ( i = 0; i < out_count; i += fade_block_size )
727 {
728 int const shift = 14;
729 int const unit = 1 << shift;
730 int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size,
731 this->fade_step, unit );
732 if ( gain < (unit >> fade_shift) )
733 this->track_ended = this->emu_track_ended_ = true;
734
735 sample_t* io = &out [i];
736 int count;
737 for ( count = min( fade_block_size, out_count - i ); count; --count )
738 {
739 *io = (sample_t) ((*io * gain) >> shift);
740 ++io;
741 }
742 } 664 }
743}
744
745// Silence detection
746 665
747static void emu_play( struct Kss_Emu* this, long count, sample_t* out ) 666 return skippy_( &this->track_filter, count );
748{
749 check( current_track_ >= 0 );
750 this->emu_time += count;
751 if ( this->current_track >= 0 && !this->emu_track_ended_ ) {
752 if ( play_( this, count, out ) )
753 this->emu_track_ended_ = true;
754 }
755 else
756 memset( out, 0, count * sizeof *out );
757} 667}
758 668
759// number of consecutive silent samples at end 669blargg_err_t Track_skip( struct Kss_Emu* this, int count )
760static long count_silence( sample_t* begin, long size )
761{ 670{
762 sample_t first = *begin; 671 require( this->current_track >= 0 ); // start_track() must have been called already
763 *begin = silence_threshold; // sentinel 672 return track_skip( &this->track_filter, count );
764 sample_t* p = begin + size;
765 while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
766 *begin = first;
767 return size - (p - begin);
768} 673}
769 674
770// fill internal buffer and check it for silence 675void Track_set_fade( struct Kss_Emu* this, int start_msec, int length_msec )
771void fill_buf( struct Kss_Emu* this )
772{ 676{
773 assert( !this->buf_remain ); 677 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
774 if ( !this->emu_track_ended_ ) 678 length_msec * this->sample_rate / (1000 / stereo) );
775 {
776 emu_play( this, buf_size, this->buf );
777 long silence = count_silence( this->buf, buf_size );
778 if ( silence < buf_size )
779 {
780 this->silence_time = this->emu_time - silence;
781 this->buf_remain = buf_size;
782 return;
783 }
784 }
785 this->silence_count += buf_size;
786} 679}
787 680
788blargg_err_t Kss_play( struct Kss_Emu* this, long out_count, sample_t* out ) 681blargg_err_t Kss_play( struct Kss_Emu* this, int out_count, sample_t* out )
789{ 682{
790 if ( this->track_ended ) 683 require( this->current_track >= 0 );
791 { 684 require( out_count % stereo == 0 );
792 memset( out, 0, out_count * sizeof *out ); 685 return track_play( &this->track_filter, out_count, out );
793 }
794 else
795 {
796 require( this->current_track >= 0 );
797 require( out_count % stereo == 0 );
798
799 assert( this->emu_time >= this->out_time );
800
801 // prints nifty graph of how far ahead we are when searching for silence
802 //debug_printf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" );
803
804 long pos = 0;
805 if ( this->silence_count )
806 {
807 // during a run of silence, run emulator at >=2x speed so it gets ahead
808 long ahead_time = this->silence_lookahead * (this->out_time + out_count -this->silence_time) + this->silence_time;
809 while ( this->emu_time < ahead_time && !(this->buf_remain |this-> emu_track_ended_) )
810 fill_buf( this );
811
812 // fill with silence
813 pos = min( this->silence_count, out_count );
814 memset( out, 0, pos * sizeof *out );
815 this->silence_count -= pos;
816
817 if ( this->emu_time - this->silence_time > silence_max * stereo * this->sample_rate )
818 {
819 this->track_ended = this->emu_track_ended_ = true;
820 this->silence_count = 0;
821 this->buf_remain = 0;
822 }
823 }
824
825 if ( this->buf_remain )
826 {
827 // empty silence buf
828 long n = min( this->buf_remain, out_count - pos );
829 memcpy( &out [pos], this->buf + (buf_size - this->buf_remain), n * sizeof *out );
830 this->buf_remain -= n;
831 pos += n;
832 }
833
834 // generate remaining samples normally
835 long remain = out_count - pos;
836 if ( remain )
837 {
838 emu_play( this, remain, out + pos );
839 this->track_ended |= this->emu_track_ended_;
840
841 if ( !this->ignore_silence || this->out_time > this->fade_start )
842 {
843 // check end for a new run of silence
844 long silence = count_silence( out + pos, remain );
845 if ( silence < remain )
846 this->silence_time = this->emu_time - silence;
847
848 if ( this->emu_time - this->silence_time >= buf_size )
849 fill_buf( this ); // cause silence detection on next play()
850 }
851 }
852
853 if ( this->out_time > this->fade_start )
854 handle_fade( this, out_count, out );
855 }
856 this->out_time += out_count;
857 return 0;
858} 686}
859 687
860blargg_err_t play_( struct Kss_Emu* this, long count, sample_t* out ) 688blargg_err_t play_( void *emu, int count, sample_t* out )
861{ 689{
862 long remain = count; 690 struct Kss_Emu* this = (struct Kss_Emu*) emu;
691
692 int remain = count;
863 while ( remain ) 693 while ( remain )
864 { 694 {
865 remain -= Buffer_read_samples( &this->stereo_buffer, &out [count - remain], remain ); 695 Buffer_disable_immediate_removal( &this->stereo_buf );
696 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
866 if ( remain ) 697 if ( remain )
867 { 698 {
868 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buffer ) ) 699 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
869 { 700 {
870 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buffer ); 701 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
702
703 // Remute voices
871 Sound_mute_voices( this, this->mute_mask_ ); 704 Sound_mute_voices( this, this->mute_mask_ );
872 } 705 }
873 int msec = Buffer_length( &this->stereo_buffer ); 706 int msec = Buffer_length( &this->stereo_buf );
874 /* blip_time_t clocks_emulated = (blargg_long) msec * clock_rate_ / 1000; */
875 blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100; 707 blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
876 RETURN_ERR( run_clocks( this, &clocks_emulated ) ); 708 RETURN_ERR( run_clocks( this, &clocks_emulated ) );
877 assert( clocks_emulated ); 709 assert( clocks_emulated );
878 Buffer_end_frame( &this->stereo_buffer, clocks_emulated ); 710 Buffer_end_frame( &this->stereo_buf, clocks_emulated );
879 } 711 }
880 } 712 }
881 return 0; 713 return 0;
882} 714}
883
diff --git a/apps/codecs/libgme/kss_emu.h b/apps/codecs/libgme/kss_emu.h
index 43df964fcc..382e4b807b 100644
--- a/apps/codecs/libgme/kss_emu.h
+++ b/apps/codecs/libgme/kss_emu.h
@@ -16,8 +16,8 @@
16#include "ay_apu.h" 16#include "ay_apu.h"
17#include "opl_apu.h" 17#include "opl_apu.h"
18#include "m3u_playlist.h" 18#include "m3u_playlist.h"
19#include "track_filter.h"
19 20
20typedef short sample_t;
21typedef int kss_time_t; 21typedef int kss_time_t;
22typedef int kss_addr_t; 22typedef int kss_addr_t;
23typedef struct Z80_Cpu Kss_Cpu; 23typedef struct Z80_Cpu Kss_Cpu;
@@ -35,7 +35,6 @@ enum {
35enum { idle_addr = 0xFFFF }; 35enum { idle_addr = 0xFFFF };
36enum { scc_enabled_true = 0xC000 }; 36enum { scc_enabled_true = 0xC000 };
37enum { mem_size = 0x10000 }; 37enum { mem_size = 0x10000 };
38enum { buf_size = 2048 };
39 38
40// KSS file header 39// KSS file header
41enum { header_size = 0x20 }; 40enum { header_size = 0x20 };
@@ -53,7 +52,7 @@ struct header_t
53 byte bank_mode; 52 byte bank_mode;
54 byte extra_header; 53 byte extra_header;
55 byte device_flags; 54 byte device_flags;
56 55
57 // KSSX extended data, if extra_header==0x10 56 // KSSX extended data, if extra_header==0x10
58 byte data_size [4]; 57 byte data_size [4];
59 byte unused [4]; 58 byte unused [4];
@@ -69,7 +68,7 @@ struct sms_t {
69 struct Sms_Apu psg; 68 struct Sms_Apu psg;
70 struct Opl_Apu fm; 69 struct Opl_Apu fm;
71}; 70};
72 71
73struct msx_t { 72struct msx_t {
74 struct Ay_Apu psg; 73 struct Ay_Apu psg;
75 struct Scc_Apu scc; 74 struct Scc_Apu scc;
@@ -84,8 +83,6 @@ struct Kss_Emu {
84 bool scc_accessed; 83 bool scc_accessed;
85 bool gain_updated; 84 bool gain_updated;
86 85
87 int track_count;
88
89 unsigned scc_enabled; // 0 or 0xC000 86 unsigned scc_enabled; // 0 or 0xC000
90 int bank_count; 87 int bank_count;
91 88
@@ -94,48 +91,34 @@ struct Kss_Emu {
94 int ay_latch; 91 int ay_latch;
95 92
96 // general 93 // general
97 int max_initial_silence;
98 int voice_count; 94 int voice_count;
95 int const* voice_types;
99 int mute_mask_; 96 int mute_mask_;
100 int tempo; 97 int tempo;
101 int gain; 98 int gain;
102 99
103 long sample_rate; 100 int sample_rate;
104 101
105 // track-specific 102 // track-specific
103 int track_count;
106 int current_track; 104 int current_track;
107 blargg_long out_time; // number of samples played since start of track
108 blargg_long emu_time; // number of samples emulator has generated since start of track
109 bool emu_track_ended_; // emulator has reached end of track
110 volatile bool track_ended;
111
112 // fading
113 blargg_long fade_start;
114 int fade_step;
115
116 // silence detection
117 int silence_lookahead; // speed to run emulator when looking ahead for silence
118 bool ignore_silence;
119 long silence_time; // number of samples where most recent silence began
120 long silence_count; // number of samples of silence to play before using buf
121 long buf_remain; // number of samples left in silence buffer
122 105
123 struct Stereo_Buffer stereo_buffer; // NULL if using custom buffer 106 int clock_rate_;
124 long clock_rate_;
125 unsigned buf_changed_count; 107 unsigned buf_changed_count;
126 108
127 // M3u Playlist 109 // M3u Playlist
128 struct M3u_Playlist m3u; 110 struct M3u_Playlist m3u;
129 111
130 // large items 112 struct setup_t tfilter;
131 sample_t buf [buf_size]; 113 struct Track_Filter track_filter;
132 114
133 struct sms_t sms; 115 struct sms_t sms;
134 struct msx_t msx; 116 struct msx_t msx;
135 117
136 Kss_Cpu cpu; 118 Kss_Cpu cpu;
119 struct Multi_Buffer stereo_buf; // NULL if using custom buffer
137 struct Rom_Data rom; 120 struct Rom_Data rom;
138 121
139 byte unmapped_read [0x100]; 122 byte unmapped_read [0x100];
140 byte unmapped_write [page_size]; 123 byte unmapped_write [page_size];
141 byte ram [mem_size + cpu_padding]; 124 byte ram [mem_size + cpu_padding];
@@ -148,34 +131,46 @@ blargg_err_t Kss_load_mem( struct Kss_Emu* this, const void* data, long size );
148blargg_err_t end_frame( struct Kss_Emu* this, kss_time_t ); 131blargg_err_t end_frame( struct Kss_Emu* this, kss_time_t );
149 132
150// Set output sample rate. Must be called only once before loading file. 133// Set output sample rate. Must be called only once before loading file.
151blargg_err_t Kss_set_sample_rate( struct Kss_Emu* this, long sample_rate ); 134blargg_err_t Kss_set_sample_rate( struct Kss_Emu* this, int sample_rate );
152 135
153// Start a track, where 0 is the first track. Also clears warning string. 136// Start a track, where 0 is the first track. Also clears warning string.
154blargg_err_t Kss_start_track( struct Kss_Emu* this, int track ); 137blargg_err_t Kss_start_track( struct Kss_Emu* this, int track );
155 138
156// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation 139// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
157// errors set warning string, and major errors also end track. 140// errors set warning string, and major errors also end track.
158blargg_err_t Kss_play( struct Kss_Emu* this, long count, sample_t* buf ); 141blargg_err_t Kss_play( struct Kss_Emu* this, int count, sample_t* buf );
159 142
160// Track status/control 143// Track status/control
161 144
162// Number of milliseconds (1000 msec = 1 second) played since beginning of track 145// Number of milliseconds (1000 msec = 1 second) played since beginning of track
163long Track_tell( struct Kss_Emu* this ); 146int Track_tell( struct Kss_Emu* this );
164 147
165// Seek to new time in track. Seeking backwards or far forward can take a while. 148// Seek to new time in track. Seeking backwards or far forward can take a while.
166blargg_err_t Track_seek( struct Kss_Emu* this, long msec ); 149blargg_err_t Track_seek( struct Kss_Emu* this, int msec );
167 150
168// Skip n samples 151// Skip n samples
169blargg_err_t Track_skip( struct Kss_Emu* this, long n ); 152blargg_err_t Track_skip( struct Kss_Emu* this, int n );
170 153
171// Set start time and length of track fade out. Once fade ends track_ended() returns 154// Set start time and length of track fade out. Once fade ends track_ended() returns
172// true. Fade time can be changed while track is playing. 155// true. Fade time can be changed while track is playing.
173void Track_set_fade( struct Kss_Emu* this, long start_msec, long length_msec ); 156void Track_set_fade( struct Kss_Emu* this, int start_msec, int length_msec );
157
158// True if a track has reached its end
159static inline bool Track_ended( struct Kss_Emu* this )
160{
161 return track_ended( &this->track_filter );
162}
163
164// Disables automatic end-of-track detection and skipping of silence at beginning
165static inline void Track_ignore_silence( struct Kss_Emu* this, bool disable )
166{
167 this->track_filter.silence_ignored_ = disable;
168}
174 169
175// Get track length in milliseconds 170// Get track length in milliseconds
176static inline long Track_get_length( struct Kss_Emu* this, int n ) 171static inline int Track_get_length( struct Kss_Emu* this, int n )
177{ 172{
178 long length = 0; 173 int length = 0;
179 174
180 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) { 175 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
181 struct entry_t* entry = &this->m3u.entries [n]; 176 struct entry_t* entry = &this->m3u.entries [n];
diff --git a/apps/codecs/libgme/kss_scc_apu.h b/apps/codecs/libgme/kss_scc_apu.h
index bb20d1d64a..a6962469ac 100644
--- a/apps/codecs/libgme/kss_scc_apu.h
+++ b/apps/codecs/libgme/kss_scc_apu.h
@@ -34,7 +34,7 @@ void Scc_reset( struct Scc_Apu* this );
34 34
35// Set overall volume, where 1.0 is normal 35// Set overall volume, where 1.0 is normal
36void Scc_volume( struct Scc_Apu* this, int v ); 36void Scc_volume( struct Scc_Apu* this, int v );
37 37
38static inline void Scc_set_output( struct Scc_Apu* this, int index, struct Blip_Buffer* b ) 38static inline void Scc_set_output( struct Scc_Apu* this, int index, struct Blip_Buffer* b )
39{ 39{
40 assert( (unsigned) index < scc_osc_count ); 40 assert( (unsigned) index < scc_osc_count );
diff --git a/apps/codecs/libgme/multi_buffer.c b/apps/codecs/libgme/multi_buffer.c
index 26cb8cdec6..554778c3de 100644
--- a/apps/codecs/libgme/multi_buffer.c
+++ b/apps/codecs/libgme/multi_buffer.c
@@ -1,4 +1,4 @@
1// Blip_Buffer 0.4.1. http://www.slack.net/~ant/ 1// Multi_Buffer 0.4.1. http://www.slack.net/~ant/
2 2
3#include "multi_buffer.h" 3#include "multi_buffer.h"
4 4
@@ -15,212 +15,272 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15 15
16#include "blargg_source.h" 16#include "blargg_source.h"
17 17
18#ifdef BLARGG_ENABLE_OPTIMIZER 18// Tracked_Blip_Buffer
19 #include BLARGG_ENABLE_OPTIMIZER 19
20#endif 20int const blip_buffer_extra = 32; // TODO: explain why this value
21 21
22// Stereo_Buffer 22void Tracked_init( struct Tracked_Blip_Buffer* this )
23 23{
24void Buffer_init( struct Stereo_Buffer* this ) 24 Blip_init( &this->blip );
25{ 25 this->last_non_silence = 0;
26 Blip_init( &this->bufs [0] );
27 Blip_init( &this->bufs [1] );
28 Blip_init( &this->bufs [2] );
29
30 this->chan.center = &this->bufs [0];
31 this->chan.left = &this->bufs [1];
32 this->chan.right = &this->bufs [2];
33
34 this->length_ = 0;
35 this->sample_rate_ = 0;
36 this->channels_changed_count_ = 1;
37 this->samples_per_frame_ = 2;
38} 26}
39 27
40blargg_err_t Buffer_set_sample_rate( struct Stereo_Buffer* this, long rate, int msec ) 28void Tracked_clear( struct Tracked_Blip_Buffer* this )
41{ 29{
42 int i; 30 this->last_non_silence = 0;
43 for ( i = 0; i < buf_count; i++ ) 31 Blip_clear( &this->blip );
44 RETURN_ERR( Blip_set_sample_rate( &this->bufs[i], rate, msec ) );
45
46 this->sample_rate_ = Blip_sample_rate( &this->bufs [0] );
47 this->length_ = Blip_length( &this->bufs [0] );
48 return 0;
49} 32}
50 33
51void Buffer_clock_rate( struct Stereo_Buffer* this, long rate ) 34void Tracked_end_frame( struct Tracked_Blip_Buffer* this, blip_time_t t )
52{ 35{
53 int i; 36 Blip_end_frame( &this->blip, t );
54 for ( i = 0; i < buf_count; i++ ) 37 if ( this->blip.modified )
55 Blip_set_clock_rate( &this->bufs [i], rate ); 38 {
39 this->blip.modified = false;
40 this->last_non_silence = Blip_samples_avail( &this->blip ) + blip_buffer_extra;
41 }
56} 42}
57 43
58void Buffer_bass_freq( struct Stereo_Buffer* this, int bass ) 44unsigned Tracked_non_silent( struct Tracked_Blip_Buffer* this )
59{ 45{
60 unsigned i; 46 return this->last_non_silence | unsettled( &this->blip );
61 for ( i = 0; i < buf_count; i++ )
62 Blip_bass_freq( &this->bufs [i], bass );
63} 47}
64 48
65struct channel_t Buffer_channel( struct Stereo_Buffer* this ) 49static inline void remove_( struct Tracked_Blip_Buffer* this, int n )
66{ 50{
67 return this->chan; 51 if ( (this->last_non_silence -= n) < 0 )
52 this->last_non_silence = 0;
68} 53}
69 54
70void Buffer_clear( struct Stereo_Buffer* this ) 55void Tracked_remove_silence( struct Tracked_Blip_Buffer* this, int n )
71{ 56{
72 this->stereo_added = 0; 57 remove_( this, n );
73 this->was_stereo = false; 58 Blip_remove_silence( &this->blip, n );
74 int i;
75 for ( i = 0; i < buf_count; i++ )
76 Blip_clear( &this->bufs [i], 1 );
77} 59}
78 60
79void Buffer_end_frame( struct Stereo_Buffer* this, blip_time_t clock_count ) 61void Tracked_remove_samples( struct Tracked_Blip_Buffer* this, int n )
62{
63 remove_( this, n );
64 Blip_remove_samples( &this->blip, n );
65}
66
67void Tracked_remove_all_samples( struct Tracked_Blip_Buffer* this )
68{
69 int avail = Blip_samples_avail( &this->blip );
70 if ( !Tracked_non_silent( this ) )
71 Tracked_remove_silence( this, avail );
72 else
73 Tracked_remove_samples( this, avail );
74}
75
76int Tracked_read_samples( struct Tracked_Blip_Buffer* this, blip_sample_t out [], int count )
77{
78 count = Blip_read_samples( &this->blip, out, count, false );
79 remove_( this, count );
80 return count;
81}
82
83// Stereo_Mixer
84
85// mixers use a single index value to improve performance on register-challenged processors
86// offset goes from negative to zero
87
88void Mixer_init( struct Stereo_Mixer* this )
80{ 89{
81 this->stereo_added = 0; 90 this->samples_read = 0;
82 unsigned i; 91}
83 for ( i = 0; i < buf_count; i++ ) 92
93static void mix_mono( struct Stereo_Mixer* this, blip_sample_t out_ [], int count )
94{
95 int const bass = this->bufs [2]->blip.bass_shift_;
96 delta_t const* center = this->bufs [2]->blip.buffer_ + this->samples_read;
97 int center_sum = this->bufs [2]->blip.reader_accum_;
98
99 typedef blip_sample_t stereo_blip_sample_t [stereo];
100 stereo_blip_sample_t* BLARGG_RESTRICT out = (stereo_blip_sample_t*) out_ + count;
101 int offset = -count;
102 do
84 { 103 {
85 this->stereo_added |= Blip_clear_modified( &this->bufs [i] ) << i; 104 int s = center_sum >> delta_bits;
86 Blip_end_frame( &this->bufs [i], clock_count ); 105
106 center_sum -= center_sum >> bass;
107 center_sum += center [offset];
108
109 BLIP_CLAMP( s, s );
110
111 out [offset] [0] = (blip_sample_t) s;
112 out [offset] [1] = (blip_sample_t) s;
87 } 113 }
114 while ( ++offset );
115
116 this->bufs [2]->blip.reader_accum_ = center_sum;
88} 117}
89 118
90long Buffer_read_samples( struct Stereo_Buffer* this, blip_sample_t* out, long count ) 119static void mix_stereo( struct Stereo_Mixer* this, blip_sample_t out_ [], int count )
91{ 120{
92 require( !(count & 1) ); // count must be even 121 blip_sample_t* BLARGG_RESTRICT out = out_ + count * stereo;
93 count = (unsigned) count / 2; 122 // do left + center and right + center separately to reduce register load
94 123 struct Tracked_Blip_Buffer* const* buf = &this->bufs [2];
95 long avail = Blip_samples_avail( &this->bufs [0] ); 124 while ( true ) // loop runs twice
96 if ( count > avail )
97 count = avail;
98 if ( count )
99 { 125 {
100 int bufs_used = this->stereo_added | this->was_stereo; 126 --buf;
101 //dprintf( "%X\n", bufs_used ); 127 --out;
102 if ( bufs_used <= 1 ) 128
103 { 129 int const bass = this->bufs [2]->blip.bass_shift_;
104 Buffer_mix_mono( this, out, count ); 130 delta_t const* side = (*buf)->blip.buffer_ + this->samples_read;
105 Blip_remove_samples( &this->bufs [0], count ); 131 delta_t const* center = this->bufs [2]->blip.buffer_ + this->samples_read;
106 Blip_remove_silence( &this->bufs [1], count ); 132
107 Blip_remove_silence( &this->bufs [2], count ); 133 int side_sum = (*buf)->blip.reader_accum_;
108 } 134 int center_sum = this->bufs [2]->blip.reader_accum_;
109 else if ( bufs_used & 1 ) 135
110 { 136 int offset = -count;
111 Buffer_mix_stereo( this, out, count ); 137 do
112 Blip_remove_samples( &this->bufs [0], count );
113 Blip_remove_samples( &this->bufs [1], count );
114 Blip_remove_samples( &this->bufs [2], count );
115 }
116 else
117 {
118 Buffer_mix_stereo_no_center( this, out, count );
119 Blip_remove_silence( &this->bufs [0], count );
120 Blip_remove_samples( &this->bufs [1], count );
121 Blip_remove_samples( &this->bufs [2], count );
122 }
123
124 // to do: this might miss opportunities for optimization
125 if ( !Blip_samples_avail( &this->bufs [0] ) )
126 { 138 {
127 this->was_stereo = this->stereo_added; 139 int s = (center_sum + side_sum) >> delta_bits;
128 this->stereo_added = 0; 140
141 side_sum -= side_sum >> bass;
142 center_sum -= center_sum >> bass;
143
144 side_sum += side [offset];
145 center_sum += center [offset];
146
147 BLIP_CLAMP( s, s );
148
149 ++offset; // before write since out is decremented to slightly before end
150 out [offset * stereo] = (blip_sample_t) s;
129 } 151 }
152 while ( offset );
153
154 (*buf)->blip.reader_accum_ = side_sum;
155
156 if ( buf != this->bufs )
157 continue;
158
159 // only end center once
160 this->bufs [2]->blip.reader_accum_ = center_sum;
161 break;
130 } 162 }
131
132 return count * 2;
133} 163}
134 164
135unsigned Buffer_channels_changed_count( struct Stereo_Buffer* this ) 165void Mixer_read_pairs( struct Stereo_Mixer* this, blip_sample_t out [], int count )
136{ 166{
137 return this->channels_changed_count_; 167 // TODO: if caller never marks buffers as modified, uses mono
168 // except that buffer isn't cleared, so caller can encounter
169 // subtle problems and not realize the cause.
170 this->samples_read += count;
171 if ( Tracked_non_silent( this->bufs [0] ) | Tracked_non_silent( this->bufs [1] ) )
172 mix_stereo( this, out, count );
173 else
174 mix_mono( this, out, count );
138} 175}
139 176
140void Buffer_channels_changed( struct Stereo_Buffer* this ) 177// Multi_Buffer
178
179void Buffer_init( struct Multi_Buffer* this )
141{ 180{
142 this->channels_changed_count_++; 181 int const spf = 2;
182
183 Tracked_init( &this->bufs [0] );
184 Tracked_init( &this->bufs [1] );
185 Tracked_init( &this->bufs [2] );
186
187 Mixer_init( &this->mixer );
188
189 this->length_ = 0;
190 this->sample_rate_ = 0;
191 this->channels_changed_count_ = 1;
192 this->channel_types_ = NULL;
193 this->channel_count_ = 0;
194 this->samples_per_frame_ = spf;
195 this->immediate_removal_ = true;
196
197 this->mixer.bufs [2] = &this->bufs [2];
198 this->mixer.bufs [0] = &this->bufs [0];
199 this->mixer.bufs [1] = &this->bufs [1];
200
201 this->chan.center = &this->bufs [2].blip;
202 this->chan.left = &this->bufs [0].blip;
203 this->chan.right = &this->bufs [1].blip;
143} 204}
144 205
145void Buffer_mix_stereo( struct Stereo_Buffer* this, blip_sample_t* out_, blargg_long count ) 206blargg_err_t Buffer_set_sample_rate( struct Multi_Buffer* this, int rate, int msec )
146{ 207{
147 blip_sample_t* BLIP_RESTRICT out = out_; 208 int i;
148 int const bass = BLIP_READER_BASS( this->bufs [1] ); 209 for ( i = bufs_size; --i >= 0; )
149 BLIP_READER_BEGIN( left, this->bufs [1] ); 210 RETURN_ERR( Blip_set_sample_rate( &this->bufs [i].blip, rate, msec ) );
150 BLIP_READER_BEGIN( right, this->bufs [2] ); 211
151 BLIP_READER_BEGIN( center, this->bufs [0] ); 212 this->sample_rate_ = Blip_sample_rate( &this->bufs [0].blip );
152 213 this->length_ = Blip_length( &this->bufs [0].blip );
153 for ( ; count; --count ) 214 return 0;
154 {
155 int c = BLIP_READER_READ( center );
156 blargg_long l = c + BLIP_READER_READ( left );
157 blargg_long r = c + BLIP_READER_READ( right );
158 if ( (int16_t) l != l )
159 l = 0x7FFF - (l >> 24);
160
161 BLIP_READER_NEXT( center, bass );
162 if ( (int16_t) r != r )
163 r = 0x7FFF - (r >> 24);
164
165 BLIP_READER_NEXT( left, bass );
166 BLIP_READER_NEXT( right, bass );
167
168 out [0] = l;
169 out [1] = r;
170 out += 2;
171 }
172
173 BLIP_READER_END( center, this->bufs [0] );
174 BLIP_READER_END( right, this->bufs [2] );
175 BLIP_READER_END( left, this->bufs [1] );
176} 215}
177 216
178void Buffer_mix_stereo_no_center( struct Stereo_Buffer* this, blip_sample_t* out_, blargg_long count ) 217void Buffer_clock_rate( struct Multi_Buffer* this, int rate )
179{ 218{
180 blip_sample_t* BLIP_RESTRICT out = out_; 219 int i;
181 int const bass = BLIP_READER_BASS( this->bufs [1] ); 220 for ( i = bufs_size; --i >= 0; )
182 BLIP_READER_BEGIN( left, this->bufs [1] ); 221 Blip_set_clock_rate( &this->bufs [i].blip, rate );
183 BLIP_READER_BEGIN( right, this->bufs [2] ); 222}
184 223
185 for ( ; count; --count ) 224void Buffer_bass_freq( struct Multi_Buffer* this, int bass )
186 { 225{
187 blargg_long l = BLIP_READER_READ( left ); 226 int i;
188 if ( (int16_t) l != l ) 227 for ( i = bufs_size; --i >= 0; )
189 l = 0x7FFF - (l >> 24); 228 Blip_bass_freq( &this->bufs [i].blip, bass );
190 229}
191 blargg_long r = BLIP_READER_READ( right ); 230
192 if ( (int16_t) r != r ) 231blargg_err_t Buffer_set_channel_count( struct Multi_Buffer* this, int n, int const* types )
193 r = 0x7FFF - (r >> 24); 232{
194 233 this->channel_count_ = n;
195 BLIP_READER_NEXT( left, bass ); 234 this->channel_types_ = types;
196 BLIP_READER_NEXT( right, bass ); 235 return 0;
197
198 out [0] = l;
199 out [1] = r;
200 out += 2;
201 }
202
203 BLIP_READER_END( right, this->bufs [2] );
204 BLIP_READER_END( left, this->bufs [1] );
205} 236}
206 237
207void Buffer_mix_mono( struct Stereo_Buffer* this, blip_sample_t* out_, blargg_long count ) 238struct channel_t Buffer_channel( struct Multi_Buffer* this, int i )
208{ 239{
209 blip_sample_t* BLIP_RESTRICT out = out_; 240 (void) i;
210 int const bass = BLIP_READER_BASS( this->bufs [0] ); 241 return this->chan;
211 BLIP_READER_BEGIN( center, this->bufs [0] ); 242}
212 243
213 for ( ; count; --count ) 244void Buffer_clear( struct Multi_Buffer* this )
245{
246 int i;
247 this->mixer.samples_read = 0;
248 for ( i = bufs_size; --i >= 0; )
249 Tracked_clear( &this->bufs [i] );
250}
251
252void Buffer_end_frame( struct Multi_Buffer* this, blip_time_t clock_count )
253{
254 int i;
255 for ( i = bufs_size; --i >= 0; )
256 Tracked_end_frame( &this->bufs [i], clock_count );
257}
258
259int Buffer_read_samples( struct Multi_Buffer* this, blip_sample_t out [], int out_size )
260{
261 require( (out_size & 1) == 0 ); // must read an even number of samples
262 out_size = min( out_size, Buffer_samples_avail( this ) );
263
264 int pair_count = (int) (out_size >> 1);
265 if ( pair_count )
214 { 266 {
215 blargg_long s = BLIP_READER_READ( center ); 267 Mixer_read_pairs( &this->mixer, out, pair_count );
216 if ( (int16_t) s != s ) 268
217 s = 0x7FFF - (s >> 24); 269 if ( Buffer_samples_avail( this ) <= 0 || this->immediate_removal_ )
218 270 {
219 BLIP_READER_NEXT( center, bass ); 271 int i;
220 out [0] = s; 272 for ( i = bufs_size; --i >= 0; )
221 out [1] = s; 273 {
222 out += 2; 274 buf_t* b = &this->bufs [i];
275 // TODO: might miss non-silence settling since it checks END of last read
276 if ( !Tracked_non_silent( b ) )
277 Tracked_remove_silence( b, this->mixer.samples_read );
278 else
279 Tracked_remove_samples( b, this->mixer.samples_read );
280 }
281 this->mixer.samples_read = 0;
282 }
223 } 283 }
224 284
225 BLIP_READER_END( center, this->bufs [0] ); 285 return out_size;
226} 286}
diff --git a/apps/codecs/libgme/multi_buffer.h b/apps/codecs/libgme/multi_buffer.h
index cfdae4f077..e5efa5a230 100644
--- a/apps/codecs/libgme/multi_buffer.h
+++ b/apps/codecs/libgme/multi_buffer.h
@@ -1,4 +1,4 @@
1// Multi-channel sound buffer interface, and basic mono and stereo buffers 1// Multi-channel sound buffer interface, stereo and effects buffers
2 2
3// Blip_Buffer 0.4.1 3// Blip_Buffer 0.4.1
4#ifndef MULTI_BUFFER_H 4#ifndef MULTI_BUFFER_H
@@ -16,57 +16,99 @@ struct channel_t {
16 16
17enum { type_index_mask = 0xFF }; 17enum { type_index_mask = 0xFF };
18enum { wave_type = 0x100, noise_type = 0x200, mixed_type = wave_type | noise_type }; 18enum { wave_type = 0x100, noise_type = 0x200, mixed_type = wave_type | noise_type };
19enum { buf_count = 3 }; 19enum { stereo = 2 };
20 20enum { bufs_size = 3 };
21struct Stereo_Buffer { 21
22 struct Blip_Buffer bufs [buf_count]; 22// Tracked_Blip_Buffer
23 struct channel_t chan; 23struct Tracked_Blip_Buffer {
24 int stereo_added; 24 struct Blip_Buffer blip;
25 int was_stereo; 25 int last_non_silence;
26 26};
27
28void Tracked_init( struct Tracked_Blip_Buffer* this );
29unsigned Tracked_non_silent( struct Tracked_Blip_Buffer* this );
30void Tracked_remove_all_samples( struct Tracked_Blip_Buffer * this );
31int Tracked_read_samples( struct Tracked_Blip_Buffer* this, blip_sample_t [], int );
32void Tracked_remove_silence( struct Tracked_Blip_Buffer* this, int );
33void Tracked_remove_samples( struct Tracked_Blip_Buffer* this, int );
34void Tracked_clear( struct Tracked_Blip_Buffer* this );
35void Tracked_end_frame( struct Tracked_Blip_Buffer* this, blip_time_t );
36
37static inline delta_t unsettled( struct Blip_Buffer* this )
38{
39 return this->reader_accum_ >> delta_bits;
40}
41
42// Stereo Mixer
43struct Stereo_Mixer {
44 struct Tracked_Blip_Buffer* bufs [3];
45 int samples_read;
46};
47
48void Mixer_init( struct Stereo_Mixer* this );
49void Mixer_read_pairs( struct Stereo_Mixer* this, blip_sample_t out [], int count );
50
51typedef struct Tracked_Blip_Buffer buf_t;
52
53// Multi_Buffer
54struct Multi_Buffer {
27 unsigned channels_changed_count_; 55 unsigned channels_changed_count_;
28 long sample_rate_; 56 int sample_rate_;
29 int length_; 57 int length_;
58 int channel_count_;
30 int samples_per_frame_; 59 int samples_per_frame_;
60 int const *channel_types_;
61 bool immediate_removal_;
62
63 buf_t bufs [bufs_size];
64 struct Stereo_Mixer mixer;
65 struct channel_t chan;
31}; 66};
32 67
33// Initializes Stereo_Buffer structure 68blargg_err_t Buffer_set_channel_count( struct Multi_Buffer* this, int n, int const* types );
34void Buffer_init( struct Stereo_Buffer* this ); 69
70// Buffers used for all channels
71static inline struct Blip_Buffer* center( struct Multi_Buffer* this ) { return &this->bufs [2].blip; }
72static inline struct Blip_Buffer* left( struct Multi_Buffer* this ) { return &this->bufs [0].blip; }
73static inline struct Blip_Buffer* right( struct Multi_Buffer* this ) { return &this->bufs [1].blip; }
35 74
36blargg_err_t Buffer_set_sample_rate( struct Stereo_Buffer* this, long, int msec ); 75// Initializes Multi_Buffer structure
37void Buffer_clock_rate( struct Stereo_Buffer* this, long ); 76void Buffer_init( struct Multi_Buffer* this );
38void Buffer_bass_freq( struct Stereo_Buffer* this, int );
39void Buffer_clear( struct Stereo_Buffer* this );
40struct channel_t Buffer_channel( struct Stereo_Buffer* this );
41void Buffer_end_frame( struct Stereo_Buffer* this, blip_time_t );
42 77
43long Buffer_read_samples( struct Stereo_Buffer* this, blip_sample_t*, long ); 78blargg_err_t Buffer_set_sample_rate( struct Multi_Buffer* this, int, int msec );
79void Buffer_clock_rate( struct Multi_Buffer* this, int );
80void Buffer_bass_freq( struct Multi_Buffer* this, int );
81void Buffer_clear( struct Multi_Buffer* this );
82void Buffer_end_frame( struct Multi_Buffer* this, blip_time_t ) ICODE_ATTR;
83
84static inline int Buffer_length( struct Multi_Buffer* this )
85{
86 return this->length_;
87}
44 88
45// Count of changes to channel configuration. Incremented whenever 89// Count of changes to channel configuration. Incremented whenever
46// a change is made to any of the Blip_Buffers for any channel. 90// a change is made to any of the Blip_Buffers for any channel.
47unsigned Buffer_channels_changed_count( struct Stereo_Buffer* this ); 91static inline unsigned Buffer_channels_changed_count( struct Multi_Buffer* this )
48void Buffer_channels_changed( struct Stereo_Buffer* this ); 92{
49 93 return this->channels_changed_count_;
50void Buffer_mix_stereo_no_center( struct Stereo_Buffer* this, blip_sample_t*, blargg_long ); 94}
51void Buffer_mix_stereo( struct Stereo_Buffer* this, blip_sample_t*, blargg_long );
52void Buffer_mix_mono( struct Stereo_Buffer* this, blip_sample_t*, blargg_long );
53 95
54// Number of samples per output frame (1 = mono, 2 = stereo) 96static inline void Buffer_disable_immediate_removal( struct Multi_Buffer* this )
55static inline int Buffer_samples_per_frame( struct Stereo_Buffer* this )
56{ 97{
57 return this->samples_per_frame_; 98 this->immediate_removal_ = false;
58} 99}
59 100
60// See Blip_Buffer.h 101static inline int Buffer_sample_rate( struct Multi_Buffer* this )
61static inline long Buffer_sample_rate( struct Stereo_Buffer* this )
62{ 102{
63 return this->sample_rate_; 103 return this->sample_rate_;
64} 104}
65 105
66// Length of buffer, in milliseconds 106static inline int Buffer_samples_avail( struct Multi_Buffer* this )
67static inline int Buffer_length( struct Stereo_Buffer* this )
68{ 107{
69 return this->length_; 108 return (Blip_samples_avail(&this->bufs [0].blip) - this->mixer.samples_read) * 2;
70} 109}
71 110
111int Buffer_read_samples( struct Multi_Buffer* this, blip_sample_t*, int ) ICODE_ATTR;
112struct channel_t Buffer_channel( struct Multi_Buffer* this, int i );
113
72#endif 114#endif
diff --git a/apps/codecs/libgme/nes_apu.c b/apps/codecs/libgme/nes_apu.c
index 7d2814b3d8..630e71f450 100644
--- a/apps/codecs/libgme/nes_apu.c
+++ b/apps/codecs/libgme/nes_apu.c
@@ -39,19 +39,19 @@ void Apu_init( struct Nes_Apu* this )
39 this->oscs [4] = &this->dmc.osc; 39 this->oscs [4] = &this->dmc.osc;
40 40
41 Apu_output( this, NULL ); 41 Apu_output( this, NULL );
42 this->dmc.nonlinear = false;
42 Apu_volume( this, (int)FP_ONE_VOLUME ); 43 Apu_volume( this, (int)FP_ONE_VOLUME );
43 Apu_reset( this, false, 0 ); 44 Apu_reset( this, false, 0 );
44} 45}
45 46
46void Apu_enable_nonlinear( struct Nes_Apu* this, int v ) 47void Apu_enable_nonlinear_( struct Nes_Apu* this, double sq, double tnd )
47{ 48{
48 this->dmc.nonlinear = true; 49 this->dmc.nonlinear = true;
49 Synth_volume( &this->square_synth, (int)((long long)(1.3 * 0.25751258 / 0.742467605 * 0.25 * FP_ONE_VOLUME) / amp_range * v) ); 50 Synth_volume( &this->square_synth, (int)((long long)(sq * FP_ONE_VOLUME) / amp_range) );
50 51
51 const int tnd = (int)(0.48 / 202 * 0.75 * FP_ONE_VOLUME); 52 Synth_volume( &this->triangle.synth, tnd * 2.752 );
52 Synth_volume( &this->triangle.synth, 3 * tnd ); 53 Synth_volume( &this->noise.synth , tnd * 1.849 );
53 Synth_volume( &this->noise.synth, 2 * tnd ); 54 Synth_volume( &this->dmc.synth , tnd );
54 Synth_volume( &this->dmc.synth, tnd );
55 55
56 this->square1 .osc.last_amp = 0; 56 this->square1 .osc.last_amp = 0;
57 this->square2 .osc.last_amp = 0; 57 this->square2 .osc.last_amp = 0;
@@ -62,11 +62,13 @@ void Apu_enable_nonlinear( struct Nes_Apu* this, int v )
62 62
63void Apu_volume( struct Nes_Apu* this, int v ) 63void Apu_volume( struct Nes_Apu* this, int v )
64{ 64{
65 this->dmc.nonlinear = false; 65 if ( !this->dmc.nonlinear )
66 Synth_volume( &this->square_synth, (int)((long long)(0.1128 *FP_ONE_VOLUME) * v / amp_range / FP_ONE_VOLUME) ); 66 {
67 Synth_volume( &this->triangle.synth,(int)((long long)(0.12765*FP_ONE_VOLUME) * v / amp_range / FP_ONE_VOLUME) ); 67 Synth_volume( &this->square_synth, (int)((long long)((0.125 * (1.0 /1.11)) * FP_ONE_VOLUME) * v / amp_range / FP_ONE_VOLUME) ); // was 0.1128 1.108
68 Synth_volume( &this->noise.synth, (int)((long long)(0.0741 *FP_ONE_VOLUME) * v / amp_range / FP_ONE_VOLUME) ); 68 Synth_volume( &this->triangle.synth,(int)((long long)((0.150 * (1.0 /1.11)) * FP_ONE_VOLUME) * v / amp_range / FP_ONE_VOLUME) ); // was 0.12765 1.175
69 Synth_volume( &this->dmc.synth, (int)((long long)(0.42545*FP_ONE_VOLUME) * v / 127 / FP_ONE_VOLUME) ); 69 Synth_volume( &this->noise.synth, (int)((long long)((0.095 * (1.0 /1.11)) * FP_ONE_VOLUME) * v / amp_range / FP_ONE_VOLUME) ); // was 0.0741 1.282
70 Synth_volume( &this->dmc.synth, (int)((long long)((0.450 * (1.0 /1.11)) * FP_ONE_VOLUME) * v / 2048 / FP_ONE_VOLUME) ); // was 0.42545 1.058
71 }
70} 72}
71 73
72void Apu_output( struct Nes_Apu* this, struct Blip_Buffer* buffer ) 74void Apu_output( struct Nes_Apu* this, struct Blip_Buffer* buffer )
diff --git a/apps/codecs/libgme/nes_apu.h b/apps/codecs/libgme/nes_apu.h
index 11f1f26cc7..0a2b1f57cd 100644
--- a/apps/codecs/libgme/nes_apu.h
+++ b/apps/codecs/libgme/nes_apu.h
@@ -1,6 +1,6 @@
1// NES 2A03 APU sound chip emulator 1// NES 2A03 APU sound chip emulator
2 2
3// Nes_Snd_Emu 0.1.8 3// Nes_Snd_Emu 0.2.0-pre
4#ifndef NES_APU_H 4#ifndef NES_APU_H
5#define NES_APU_H 5#define NES_APU_H
6 6
@@ -9,7 +9,7 @@
9 9
10enum { apu_status_addr = 0x4015 }; 10enum { apu_status_addr = 0x4015 };
11enum { apu_osc_count = 5 }; 11enum { apu_osc_count = 5 };
12enum { apu_no_irq = INT_MAX / 2 + 1 }; 12enum { apu_no_irq = INT_MAX/2 + 1 };
13enum { apu_irq_waiting = 0 }; 13enum { apu_irq_waiting = 0 };
14 14
15enum { apu_io_addr = 0x4000 }; 15enum { apu_io_addr = 0x4000 };
@@ -17,24 +17,16 @@ enum { apu_io_size = 0x18 };
17 17
18struct apu_state_t; 18struct apu_state_t;
19 19
20struct Nes_Apu { 20struct Nes_Apu {
21 nes_time_t last_dmc_time;
22 int osc_enables;
23
24 struct Nes_Osc* oscs [apu_osc_count];
25 struct Nes_Square square1;
26 struct Nes_Square square2;
27 struct Nes_Noise noise;
28 struct Nes_Triangle triangle;
29 struct Nes_Dmc dmc;
30
31 int tempo_; 21 int tempo_;
32 nes_time_t last_time; // has been run until this time in current frame 22 nes_time_t last_time; // has been run until this time in current frame
23 nes_time_t last_dmc_time;
33 nes_time_t earliest_irq_; 24 nes_time_t earliest_irq_;
34 nes_time_t next_irq; 25 nes_time_t next_irq;
35 int frame_period; 26 int frame_period;
36 int frame_delay; // cycles until frame counter runs next 27 int frame_delay; // cycles until frame counter runs next
37 int frame; // current frame (0-3) 28 int frame; // current frame (0-3)
29 int osc_enables;
38 int frame_mode; 30 int frame_mode;
39 bool irq_flag; 31 bool irq_flag;
40 32
@@ -42,6 +34,13 @@ struct Nes_Apu {
42 void* irq_data; 34 void* irq_data;
43 35
44 Synth square_synth; // shared by squares 36 Synth square_synth; // shared by squares
37
38 struct Nes_Osc* oscs [apu_osc_count];
39 struct Nes_Square square1;
40 struct Nes_Square square2;
41 struct Nes_Noise noise;
42 struct Nes_Triangle triangle;
43 struct Nes_Dmc dmc;
45}; 44};
46 45
47// Init Nes apu 46// Init Nes apu
@@ -49,22 +48,22 @@ void Apu_init( struct Nes_Apu* this );
49 48
50// Set buffer to generate all sound into, or disable sound if NULL 49// Set buffer to generate all sound into, or disable sound if NULL
51void Apu_output( struct Nes_Apu* this, struct Blip_Buffer* ); 50void Apu_output( struct Nes_Apu* this, struct Blip_Buffer* );
52 51
53// All time values are the number of cpu clock cycles relative to the 52// All time values are the number of cpu clock cycles relative to the
54// beginning of the current time frame. Before resetting the cpu clock 53// beginning of the current time frame. Before resetting the cpu clock
55// count, call end_frame( last_cpu_time ). 54// count, call end_frame( last_cpu_time ).
56 55
57// Write to register (0x4000-0x4017, except 0x4014 and 0x4016) 56// Write to register (0x4000-0x4017, except 0x4014 and 0x4016)
58void Apu_write_register( struct Nes_Apu* this, nes_time_t, addr_t, int data ); 57void Apu_write_register( struct Nes_Apu* this, nes_time_t, addr_t, int data );
59 58
60// Read from status register at 0x4015 59// Read from status register at 0x4015
61int Apu_read_status( struct Nes_Apu* this, nes_time_t ); 60int Apu_read_status( struct Nes_Apu* this, nes_time_t );
62 61
63// Run all oscillators up to specified time, end current time frame, then 62// Run all oscillators up to specified time, end current time frame, then
64// start a new time frame at time 0. Time frames have no effect on emulation 63// start a new time frame at time 0. Time frames have no effect on emulation
65// and each can be whatever length is convenient. 64// and each can be whatever length is convenient.
66void Apu_end_frame( struct Nes_Apu* this, nes_time_t ); 65void Apu_end_frame( struct Nes_Apu* this, nes_time_t );
67 66
68// Additional optional features (can be ignored without any problem) 67// Additional optional features (can be ignored without any problem)
69 68
70// Reset internal frame counter, registers, and all oscillators. 69// Reset internal frame counter, registers, and all oscillators.
@@ -72,13 +71,13 @@ void Apu_end_frame( struct Nes_Apu* this, nes_time_t );
72// Set the DMC oscillator's initial DAC value to initial_dmc_dac without 71// Set the DMC oscillator's initial DAC value to initial_dmc_dac without
73// any audible click. 72// any audible click.
74void Apu_reset( struct Nes_Apu* this, bool pal_mode, int initial_dmc_dac ); 73void Apu_reset( struct Nes_Apu* this, bool pal_mode, int initial_dmc_dac );
75 74
76// Adjust frame period 75// Adjust frame period
77void Apu_set_tempo( struct Nes_Apu* this, int ); 76void Apu_set_tempo( struct Nes_Apu* this, int );
78 77
79// Set overall volume (default is 1.0) 78// Set overall volume (default is 1.0)
80void Apu_volume( struct Nes_Apu* this, int ); 79void Apu_volume( struct Nes_Apu* this, int );
81 80
82// Run DMC until specified time, so that any DMC memory reads can be 81// Run DMC until specified time, so that any DMC memory reads can be
83// accounted for (i.e. inserting cpu wait states). 82// accounted for (i.e. inserting cpu wait states).
84void Apu_run_until( struct Nes_Apu* this, nes_time_t ); 83void Apu_run_until( struct Nes_Apu* this, nes_time_t );
@@ -124,11 +123,13 @@ static inline nes_time_t Dmc_next_read_time( struct Nes_Dmc* this )
124 if ( this->osc.length_counter == 0 ) 123 if ( this->osc.length_counter == 0 )
125 return apu_no_irq; // not reading 124 return apu_no_irq; // not reading
126 125
127 return this->apu->last_dmc_time + this->osc.delay + (long) (this->bits_remain - 1) * this->period; 126 return this->apu->last_dmc_time + this->osc.delay + (this->bits_remain - 1) * this->period;
128} 127}
129 128
130// Time when next DMC memory read will occur 129// Time when next DMC memory read will occur
131static inline nes_time_t Apu_next_dmc_read_time( struct Nes_Apu* this ) { return Dmc_next_read_time( &this->dmc ); } 130static inline nes_time_t Apu_next_dmc_read_time( struct Nes_Apu* this ) { return Dmc_next_read_time( &this->dmc ); }
132void Apu_irq_changed( struct Nes_Apu* this ); 131void Apu_irq_changed( struct Nes_Apu* this );
133 132
133// Experimental
134void Apu_enable_nonlinear_( struct Nes_Apu* this, double sq, double tnd );
134#endif 135#endif
diff --git a/apps/codecs/libgme/nes_cpu_io.h b/apps/codecs/libgme/nes_cpu_io.h
deleted file mode 100644
index 4f9d416c2d..0000000000
--- a/apps/codecs/libgme/nes_cpu_io.h
+++ /dev/null
@@ -1,94 +0,0 @@
1
2#include "nsf_emu.h"
3
4#ifndef NSF_EMU_APU_ONLY
5 #include "nes_namco_apu.h"
6 #include "nes_fds_apu.h"
7 #include "nes_mmc5_apu.h"
8#endif
9
10#include "blargg_source.h"
11
12int Cpu_read( struct Nsf_Emu* this, nes_addr_t addr )
13{
14 int result = this->cpu.low_mem [addr & 0x7FF];
15 if ( addr & 0xE000 )
16 {
17 result = *Cpu_get_code( &this->cpu, addr );
18 if ( addr < sram_addr )
19 {
20 if ( addr == status_addr )
21 result = Apu_read_status( &this->apu, Cpu_time( &this->cpu ) );
22 else
23 {
24 #ifndef NSF_EMU_APU_ONLY
25 if ( namco_enabled( this ) && addr == namco_data_reg_addr )
26 return Namco_read_data( &this->namco );
27
28 if ( fds_enabled( this ) && (unsigned) (addr - fds_io_addr) < fds_io_size )
29 return Fds_read( &this->fds, Cpu_time( &this->cpu ), addr );
30
31 if ( mmc5_enabled( this ) ) {
32 int i = addr - 0x5C00;
33 if ( (unsigned) i < mmc5_exram_size )
34 return this->mmc5.exram [i];
35
36 int m = addr - 0x5205;
37 if ( (unsigned) m < 2 )
38 return (this->mmc5_mul [0] * this->mmc5_mul [1]) >> (m * 8) & 0xFF;
39 }
40 #endif
41 result = addr >> 8; // simulate open bus
42 }
43 }
44 }
45
46 /* if ( addr != 0x2002 )
47 debug_printf( "Read unmapped $%.4X\n", (unsigned) addr ); */
48
49 return result;
50}
51
52void Cpu_write( struct Nsf_Emu* this, nes_addr_t addr, int data )
53{
54 int offset = addr - sram_addr;
55 if ( (unsigned) offset < sram_size )
56 {
57 this->sram [offset] = data;
58 }
59 else
60 {
61 // after sram because cpu handles most low_ram accesses internally already
62 int temp = addr & (low_ram_size-1); // also handles wrap-around
63 if ( !(addr & 0xE000) )
64 {
65 this->cpu.low_mem [temp] = data;
66 }
67 else
68 {
69 int bank = addr - banks_addr;
70 if ( (unsigned) bank < bank_count )
71 {
72 Write_bank( this, bank, data );
73 }
74 else if ( (unsigned) (addr - start_addr) <= end_addr - start_addr )
75 {
76 Apu_write_register( &this->apu, Cpu_time( &this->cpu ), addr, data );
77 }
78 else
79 {
80 #ifndef NSF_EMU_APU_ONLY
81 // 0x8000-0xDFFF is writable
82 int i = addr - 0x8000;
83 if ( fds_enabled( this ) && (unsigned) i < fdsram_size )
84 fdsram( this ) [i] = data;
85 else
86 #endif
87 Cpu_write_misc( this, addr, data );
88 }
89 }
90 }
91}
92
93#define CPU_READ( emu, addr, time ) Cpu_read( emu, addr )
94#define CPU_WRITE( emu, addr, data, time ) Cpu_write( emu, addr, data )
diff --git a/apps/codecs/libgme/nes_fme7_apu.c b/apps/codecs/libgme/nes_fme7_apu.c
index 8a2c21ea26..3e47e0b17c 100644
--- a/apps/codecs/libgme/nes_fme7_apu.c
+++ b/apps/codecs/libgme/nes_fme7_apu.c
@@ -64,8 +64,6 @@ void Fme7_run_until( struct Nes_Fme7_Apu* this, blip_time_t end_time )
64 struct Blip_Buffer* const osc_output = this->oscs [index].output; 64 struct Blip_Buffer* const osc_output = this->oscs [index].output;
65 if ( !osc_output ) 65 if ( !osc_output )
66 continue; 66 continue;
67 /* osc_output->set_modified(); */
68 Blip_set_modified( osc_output );
69 67
70 // check for unsupported mode 68 // check for unsupported mode
71 #ifndef NDEBUG 69 #ifndef NDEBUG
@@ -92,11 +90,13 @@ void Fme7_run_until( struct Nes_Fme7_Apu* this, blip_time_t end_time )
92 int amp = volume; 90 int amp = volume;
93 if ( !this->phases [index] ) 91 if ( !this->phases [index] )
94 amp = 0; 92 amp = 0;
93
95 { 94 {
96 int delta = amp - this->oscs [index].last_amp; 95 int delta = amp - this->oscs [index].last_amp;
97 if ( delta ) 96 if ( delta )
98 { 97 {
99 this->oscs [index].last_amp = amp; 98 this->oscs [index].last_amp = amp;
99 Blip_set_modified( osc_output );
100 Synth_offset( &this->synth, this->last_time, delta, osc_output ); 100 Synth_offset( &this->synth, this->last_time, delta, osc_output );
101 } 101 }
102 } 102 }
@@ -105,6 +105,7 @@ void Fme7_run_until( struct Nes_Fme7_Apu* this, blip_time_t end_time )
105 if ( time < end_time ) 105 if ( time < end_time )
106 { 106 {
107 int delta = amp * 2 - volume; 107 int delta = amp * 2 - volume;
108 Blip_set_modified( osc_output );
108 if ( volume ) 109 if ( volume )
109 { 110 {
110 do 111 do
@@ -123,7 +124,7 @@ void Fme7_run_until( struct Nes_Fme7_Apu* this, blip_time_t end_time )
123 // maintain phase when silent 124 // maintain phase when silent
124 int count = (end_time - time + period - 1) / period; 125 int count = (end_time - time + period - 1) / period;
125 this->phases [index] ^= count & 1; 126 this->phases [index] ^= count & 1;
126 time += (blargg_long) count * period; 127 time += count * period;
127 } 128 }
128 } 129 }
129 130
diff --git a/apps/codecs/libgme/nes_fme7_apu.h b/apps/codecs/libgme/nes_fme7_apu.h
index 353d82d1df..c0eac4c765 100644
--- a/apps/codecs/libgme/nes_fme7_apu.h
+++ b/apps/codecs/libgme/nes_fme7_apu.h
@@ -1,6 +1,6 @@
1// Sunsoft FME-7 sound emulator 1// Sunsoft FME-7 sound emulator
2 2
3// Game_Music_Emu 0.5.5 3// Game_Music_Emu 0.6-pre
4#ifndef NES_FME7_APU_H 4#ifndef NES_FME7_APU_H
5#define NES_FME7_APU_H 5#define NES_FME7_APU_H
6 6
diff --git a/apps/codecs/libgme/nes_namco_apu.c b/apps/codecs/libgme/nes_namco_apu.c
index 0f64d3c84f..34df200bb6 100644
--- a/apps/codecs/libgme/nes_namco_apu.c
+++ b/apps/codecs/libgme/nes_namco_apu.c
@@ -68,8 +68,6 @@ void Namco_run_until( struct Nes_Namco_Apu* this, blip_time_t nes_end_time )
68 struct Blip_Buffer* output = osc->output; 68 struct Blip_Buffer* output = osc->output;
69 if ( !output ) 69 if ( !output )
70 continue; 70 continue;
71 /* output->set_modified(); */
72 Blip_set_modified( output );
73 71
74 blip_resampled_time_t time = 72 blip_resampled_time_t time =
75 Blip_resampled_time( output, this->last_time ) + osc->delay; 73 Blip_resampled_time( output, this->last_time ) + osc->delay;
@@ -85,12 +83,17 @@ void Namco_run_until( struct Nes_Namco_Apu* this, blip_time_t nes_end_time )
85 if ( !volume ) 83 if ( !volume )
86 continue; 84 continue;
87 85
88 blargg_long freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100L + osc_reg [0]; 86 int freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100L + osc_reg [0];
89 if ( freq < 64 * active_oscs ) 87 if ( freq < 64 * active_oscs )
90 continue; // prevent low frequencies from excessively delaying freq changes 88 continue; // prevent low frequencies from excessively delaying freq changes
89
90 int const master_clock_divider = 12; // NES time derived via divider of master clock
91 int const n106_divider = 45; // N106 then divides master clock by this
92 int const max_freq = 0x3FFFF;
93 int const lowest_freq_period = (max_freq + 1) * n106_divider / master_clock_divider;
94 // divide by 8 to avoid overflow
91 blip_resampled_time_t period = 95 blip_resampled_time_t period =
92 /* output->resampled_duration( 983040 ) / freq * active_oscs; */ 96 Blip_resampled_duration( output, lowest_freq_period / 8 ) / freq * 8 * active_oscs;
93 Blip_resampled_duration( output, 983040 ) / freq * active_oscs;
94 97
95 int wave_size = 32 - (osc_reg [4] >> 2 & 7) * 4; 98 int wave_size = 32 - (osc_reg [4] >> 2 & 7) * 4;
96 if ( !wave_size ) 99 if ( !wave_size )
@@ -99,6 +102,8 @@ void Namco_run_until( struct Nes_Namco_Apu* this, blip_time_t nes_end_time )
99 int last_amp = osc->last_amp; 102 int last_amp = osc->last_amp;
100 int wave_pos = osc->wave_pos; 103 int wave_pos = osc->wave_pos;
101 104
105 Blip_set_modified( output );
106
102 do 107 do
103 { 108 {
104 // read wave sample 109 // read wave sample
diff --git a/apps/codecs/libgme/nes_namco_apu.h b/apps/codecs/libgme/nes_namco_apu.h
index c47eacc4bb..c428c894c3 100644
--- a/apps/codecs/libgme/nes_namco_apu.h
+++ b/apps/codecs/libgme/nes_namco_apu.h
@@ -15,13 +15,13 @@ enum { namco_data_reg_addr = 0x4800 };
15enum { namco_reg_count = 0x80 }; 15enum { namco_reg_count = 0x80 };
16 16
17struct Namco_Osc { 17struct Namco_Osc {
18 blargg_long delay; 18 int delay;
19 struct Blip_Buffer* output; 19 struct Blip_Buffer* output;
20 short last_amp; 20 short last_amp;
21 short wave_pos; 21 short wave_pos;
22}; 22};
23 23
24struct Nes_Namco_Apu { 24struct Nes_Namco_Apu {
25 struct Namco_Osc oscs [namco_osc_count]; 25 struct Namco_Osc oscs [namco_osc_count];
26 26
27 blip_time_t last_time; 27 blip_time_t last_time;
diff --git a/apps/codecs/libgme/nes_oscs.c b/apps/codecs/libgme/nes_oscs.c
index 4402b60a61..f97ce2176d 100644
--- a/apps/codecs/libgme/nes_oscs.c
+++ b/apps/codecs/libgme/nes_oscs.c
@@ -90,7 +90,7 @@ static inline nes_time_t Square_maintain_phase( struct Nes_Square* this, nes_tim
90 { 90 {
91 int count = (remain + timer_period - 1) / timer_period; 91 int count = (remain + timer_period - 1) / timer_period;
92 this->phase = (this->phase + count) & (square_phase_range - 1); 92 this->phase = (this->phase + count) & (square_phase_range - 1);
93 time += (blargg_long) count * timer_period; 93 time += count * timer_period;
94 } 94 }
95 return time; 95 return time;
96} 96}
@@ -107,8 +107,6 @@ void Square_run( struct Nes_Square* this, nes_time_t time, nes_time_t end_time )
107 return; 107 return;
108 } 108 }
109 109
110 Blip_set_modified( osc->output );
111
112 int offset = period >> (osc->regs [1] & shift_mask); 110 int offset = period >> (osc->regs [1] & shift_mask);
113 if ( osc->regs [1] & negate_flag ) 111 if ( osc->regs [1] & negate_flag )
114 offset = 0; 112 offset = 0;
@@ -117,6 +115,7 @@ void Square_run( struct Nes_Square* this, nes_time_t time, nes_time_t end_time )
117 if ( volume == 0 || period < 8 || (period + offset) >= 0x800 ) 115 if ( volume == 0 || period < 8 || (period + offset) >= 0x800 )
118 { 116 {
119 if ( osc->last_amp ) { 117 if ( osc->last_amp ) {
118 Blip_set_modified( osc->output );
120 Synth_offset( this->synth, time, -osc->last_amp, osc->output ); 119 Synth_offset( this->synth, time, -osc->last_amp, osc->output );
121 osc->last_amp = 0; 120 osc->last_amp = 0;
122 } 121 }
@@ -137,6 +136,7 @@ void Square_run( struct Nes_Square* this, nes_time_t time, nes_time_t end_time )
137 if ( this->phase < duty ) 136 if ( this->phase < duty )
138 amp ^= volume; 137 amp ^= volume;
139 138
139 Blip_set_modified( osc->output );
140 { 140 {
141 int delta = Osc_update_amp( osc, amp ); 141 int delta = Osc_update_amp( osc, amp );
142 if ( delta ) 142 if ( delta )
@@ -201,7 +201,7 @@ static inline nes_time_t Triangle_maintain_phase( struct Nes_Triangle* this, nes
201 int count = (remain + timer_period - 1) / timer_period; 201 int count = (remain + timer_period - 1) / timer_period;
202 this->phase = ((unsigned) this->phase + 1 - count) & (Triangle_phase_range * 2 - 1); 202 this->phase = ((unsigned) this->phase + 1 - count) & (Triangle_phase_range * 2 - 1);
203 this->phase++; 203 this->phase++;
204 time += (blargg_long) count * timer_period; 204 time += count * timer_period;
205 } 205 }
206 return time; 206 return time;
207} 207}
@@ -219,14 +219,15 @@ void Triangle_run( struct Nes_Triangle* this, nes_time_t time, nes_time_t end_ti
219 return; 219 return;
220 } 220 }
221 221
222 Blip_set_modified( osc->output );
223
224 // to do: track phase when period < 3 222 // to do: track phase when period < 3
225 // to do: Output 7.5 on dac when period < 2? More accurate, but results in more clicks. 223 // to do: Output 7.5 on dac when period < 2? More accurate, but results in more clicks.
226 224
227 int delta = Osc_update_amp( osc, Triangle_calc_amp( this ) ); 225 int delta = Osc_update_amp( osc, Triangle_calc_amp( this ) );
228 if ( delta ) 226 if ( delta )
227 {
228 Blip_set_modified( osc->output );
229 Synth_offset( &this->synth, time, delta, osc->output ); 229 Synth_offset( &this->synth, time, delta, osc->output );
230 }
230 231
231 time += osc->delay; 232 time += osc->delay;
232 if ( osc->length_counter == 0 || this->linear_counter == 0 || timer_period < 3 ) 233 if ( osc->length_counter == 0 || this->linear_counter == 0 || timer_period < 3 )
@@ -243,13 +244,15 @@ void Triangle_run( struct Nes_Triangle* this, nes_time_t time, nes_time_t end_ti
243 phase -= Triangle_phase_range; 244 phase -= Triangle_phase_range;
244 volume = -volume; 245 volume = -volume;
245 } 246 }
247 Blip_set_modified( osc->output );
246 248
247 do { 249 do {
248 if ( --phase == 0 ) { 250 if ( --phase == 0 ) {
249 phase = Triangle_phase_range; 251 phase = Triangle_phase_range;
250 volume = -volume; 252 volume = -volume;
251 } 253 }
252 else { 254 else
255 {
253 Synth_offset_inline( &this->synth, time, volume, output ); 256 Synth_offset_inline( &this->synth, time, volume, output );
254 } 257 }
255 258
@@ -340,18 +343,27 @@ static inline void Dmc_reload_sample( struct Nes_Dmc* this )
340 this->osc.length_counter = this->osc.regs [3] * 0x10 + 1; 343 this->osc.length_counter = this->osc.regs [3] * 0x10 + 1;
341} 344}
342 345
343static byte const dac_table [128] = 346static int const dmc_table [128] =
344{ 347{
345 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9,10,11,12,13,14, 348 0, 24, 48, 71, 94, 118, 141, 163, 186, 209, 231, 253, 275, 297, 319, 340,
346 15,15,16,17,18,19,20,20,21,22,23,24,24,25,26,27, 349 361, 383, 404, 425, 445, 466, 486, 507, 527, 547, 567, 587, 606, 626, 645, 664,
347 27,28,29,30,31,31,32,33,33,34,35,36,36,37,38,38, 350 683, 702, 721, 740, 758, 777, 795, 813, 832, 850, 867, 885, 903, 920, 938, 955,
348 39,40,41,41,42,43,43,44,45,45,46,47,47,48,48,49, 351 972, 989,1006,1023,1040,1056,1073,1089,1105,1122,1138,1154,1170,1185,1201,1217,
349 50,50,51,52,52,53,53,54,55,55,56,56,57,58,58,59, 3521232,1248,1263,1278,1293,1308,1323,1338,1353,1368,1382,1397,1411,1425,1440,1454,
350 59,60,60,61,61,62,63,63,64,64,65,65,66,66,67,67, 3531468,1482,1496,1510,1523,1537,1551,1564,1578,1591,1604,1618,1631,1644,1657,1670,
351 68,68,69,70,70,71,71,72,72,73,73,74,74,75,75,75, 3541683,1695,1708,1721,1733,1746,1758,1771,1783,1795,1807,1819,1831,1843,1855,1867,
352 76,76,77,77,78,78,79,79,80,80,81,81,82,82,82,83, 3551879,1890,1902,1914,1925,1937,1948,1959,1971,1982,1993,2004,2015,2026,2037,2048,
353}; 356};
354 357
358static inline int update_amp_nonlinear( struct Nes_Dmc* this, int in )
359{
360 if ( !this->nonlinear )
361 in = dmc_table [in];
362 int delta = in - this->osc.last_amp;
363 this->osc.last_amp = in;
364 return delta;
365}
366
355void Dmc_write_register( struct Nes_Dmc* this, int addr, int data ) 367void Dmc_write_register( struct Nes_Dmc* this, int addr, int data )
356{ 368{
357 if ( addr == 0 ) 369 if ( addr == 0 )
@@ -363,14 +375,7 @@ void Dmc_write_register( struct Nes_Dmc* this, int addr, int data )
363 } 375 }
364 else if ( addr == 1 ) 376 else if ( addr == 1 )
365 { 377 {
366 int old_dac = this->dac;
367 this->dac = data & 0x7F; 378 this->dac = data & 0x7F;
368
369 // adjust last_amp so that "pop" amplitude will be properly non-linear
370 // with respect to change in dac
371 int faked_nonlinear = this->dac - (dac_table [this->dac] - dac_table [old_dac]);
372 if ( !this->nonlinear )
373 this->osc.last_amp = faked_nonlinear;
374 } 379 }
375} 380}
376 381
@@ -407,16 +412,15 @@ void Dmc_fill_buffer( struct Nes_Dmc* this )
407void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time ) 412void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time )
408{ 413{
409 struct Nes_Osc* osc = &this->osc; 414 struct Nes_Osc* osc = &this->osc;
410 int delta = Osc_update_amp( osc, this->dac ); 415 int delta = update_amp_nonlinear( this, this->dac );
411 if ( !osc->output ) 416 if ( !osc->output )
412 { 417 {
413 this->silence = true; 418 this->silence = true;
414 } 419 }
415 else 420 else if ( delta )
416 { 421 {
417 Blip_set_modified( osc->output ); 422 Blip_set_modified( osc->output );
418 if ( delta ) 423 Synth_offset( &this->synth, time, delta, osc->output );
419 Synth_offset( &this->synth, time, delta, osc->output );
420 } 424 }
421 425
422 time += osc->delay; 426 time += osc->delay;
@@ -435,6 +439,8 @@ void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time )
435 const int period = this->period; 439 const int period = this->period;
436 int bits = this->bits; 440 int bits = this->bits;
437 int dac = this->dac; 441 int dac = this->dac;
442 if ( output )
443 Blip_set_modified( output );
438 444
439 do 445 do
440 { 446 {
@@ -444,7 +450,7 @@ void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time )
444 bits >>= 1; 450 bits >>= 1;
445 if ( (unsigned) (dac + step) <= 0x7F ) { 451 if ( (unsigned) (dac + step) <= 0x7F ) {
446 dac += step; 452 dac += step;
447 Synth_offset_inline( &this->synth, time, step, output ); 453 Synth_offset_inline( &this->synth, time, update_amp_nonlinear( this, dac ), output );
448 } 454 }
449 } 455 }
450 456
@@ -456,7 +462,8 @@ void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time )
456 if ( !this->buf_full ) { 462 if ( !this->buf_full ) {
457 this->silence = true; 463 this->silence = true;
458 } 464 }
459 else { 465 else
466 {
460 this->silence = false; 467 this->silence = false;
461 bits = this->buf; 468 bits = this->buf;
462 this->buf_full = false; 469 this->buf_full = false;
@@ -469,7 +476,7 @@ void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time )
469 while ( time < end_time ); 476 while ( time < end_time );
470 477
471 this->dac = dac; 478 this->dac = dac;
472 osc->last_amp = dac; 479 //osc->last_amp = dac;
473 this->bits = bits; 480 this->bits = bits;
474 } 481 }
475 this->bits_remain = bits_remain; 482 this->bits_remain = bits_remain;
@@ -519,14 +526,15 @@ void Noise_run( struct Nes_Noise* this, nes_time_t time, nes_time_t end_time )
519 return; 526 return;
520 } 527 }
521 528
522 Blip_set_modified( osc->output );
523
524 const int volume = Noise_volume( this ); 529 const int volume = Noise_volume( this );
525 int amp = (this->noise & 1) ? volume : 0; 530 int amp = (this->noise & 1) ? volume : 0;
526 { 531 {
527 int delta = Osc_update_amp( osc, amp ); 532 int delta = Osc_update_amp( osc, amp );
528 if ( delta ) 533 if ( delta )
534 {
535 Blip_set_modified( osc->output );
529 Synth_offset( &this->synth, time, delta, osc->output ); 536 Synth_offset( &this->synth, time, delta, osc->output );
537 }
530 } 538 }
531 539
532 time += osc->delay; 540 time += osc->delay;
@@ -557,6 +565,7 @@ void Noise_run( struct Nes_Noise* this, nes_time_t time, nes_time_t end_time )
557 int noise = this->noise; 565 int noise = this->noise;
558 int delta = amp * 2 - volume; 566 int delta = amp * 2 - volume;
559 const int tap = (osc->regs [2] & mode_flag ? 8 : 13); 567 const int tap = (osc->regs [2] & mode_flag ? 8 : 13);
568 Blip_set_modified( osc->output );
560 569
561 do { 570 do {
562 int feedback = (noise << tap) ^ (noise << 14); 571 int feedback = (noise << tap) ^ (noise << 14);
diff --git a/apps/codecs/libgme/nes_oscs.h b/apps/codecs/libgme/nes_oscs.h
index fa6b8ab4b0..1eeb302e6c 100644
--- a/apps/codecs/libgme/nes_oscs.h
+++ b/apps/codecs/libgme/nes_oscs.h
@@ -46,7 +46,7 @@ enum { shift_mask = 0x07 };
46enum { square_phase_range = 8 }; 46enum { square_phase_range = 8 };
47 47
48typedef struct Blip_Synth Synth; 48typedef struct Blip_Synth Synth;
49 49
50struct Nes_Square 50struct Nes_Square
51{ 51{
52 struct Nes_Osc osc; 52 struct Nes_Osc osc;
@@ -54,12 +54,12 @@ struct Nes_Square
54 int env_delay; 54 int env_delay;
55 int phase; 55 int phase;
56 int sweep_delay; 56 int sweep_delay;
57 57
58 Synth* synth; // shared between squares 58 Synth* synth; // shared between squares
59}; 59};
60 60
61static inline void Square_set_synth( struct Nes_Square* this, Synth* s ) { this->synth = s; } 61static inline void Square_set_synth( struct Nes_Square* this, Synth* s ) { this->synth = s; }
62 62
63void Square_clock_sweep( struct Nes_Square* this, int adjust ); 63void Square_clock_sweep( struct Nes_Square* this, int adjust );
64void Square_run( struct Nes_Square* this, nes_time_t, nes_time_t ); 64void Square_run( struct Nes_Square* this, nes_time_t, nes_time_t );
65 65
@@ -73,15 +73,15 @@ static inline void Square_reset( struct Nes_Square* this )
73 73
74void Square_clock_envelope( struct Nes_Square* this ); 74void Square_clock_envelope( struct Nes_Square* this );
75int Square_volume( struct Nes_Square* this ); 75int Square_volume( struct Nes_Square* this );
76 76
77// Nes_Triangle 77// Nes_Triangle
78 78
79enum { Triangle_phase_range = 16 }; 79enum { Triangle_phase_range = 16 };
80 80
81struct Nes_Triangle 81struct Nes_Triangle
82{ 82{
83 struct Nes_Osc osc; 83 struct Nes_Osc osc;
84 84
85 int phase; 85 int phase;
86 int linear_counter; 86 int linear_counter;
87 struct Blip_Synth synth; 87 struct Blip_Synth synth;
@@ -123,11 +123,11 @@ static inline void Noise_reset( struct Nes_Noise* this )
123// Nes_Dmc 123// Nes_Dmc
124 124
125enum { loop_flag = 0x40 }; 125enum { loop_flag = 0x40 };
126 126
127struct Nes_Dmc 127struct Nes_Dmc
128{ 128{
129 struct Nes_Osc osc; 129 struct Nes_Osc osc;
130 130
131 int address; // address of next byte to read 131 int address; // address of next byte to read
132 int period; 132 int period;
133 int buf; 133 int buf;
@@ -144,7 +144,7 @@ struct Nes_Dmc
144 bool pal_mode; 144 bool pal_mode;
145 bool nonlinear; 145 bool nonlinear;
146 146
147 int (*prg_reader)( void*, addr_t ); // needs to be initialized to prg read function 147 int (*prg_reader)( void*, int ); // needs to be initialized to prg read function
148 void* prg_reader_data; 148 void* prg_reader_data;
149 149
150 struct Nes_Apu* apu; 150 struct Nes_Apu* apu;
diff --git a/apps/codecs/libgme/nes_vrc6_apu.c b/apps/codecs/libgme/nes_vrc6_apu.c
index f712216424..55fccb7b0f 100644
--- a/apps/codecs/libgme/nes_vrc6_apu.c
+++ b/apps/codecs/libgme/nes_vrc6_apu.c
@@ -83,7 +83,6 @@ void run_square( struct Nes_Vrc6_Apu* this, struct Vrc6_Osc* osc, blip_time_t en
83 struct Blip_Buffer* output = osc->output; 83 struct Blip_Buffer* output = osc->output;
84 if ( !output ) 84 if ( !output )
85 return; 85 return;
86 Blip_set_modified( output );
87 86
88 int volume = osc->regs [0] & 15; 87 int volume = osc->regs [0] & 15;
89 if ( !(osc->regs [2] & 0x80) ) 88 if ( !(osc->regs [2] & 0x80) )
@@ -96,6 +95,7 @@ void run_square( struct Nes_Vrc6_Apu* this, struct Vrc6_Osc* osc, blip_time_t en
96 if ( delta ) 95 if ( delta )
97 { 96 {
98 osc->last_amp += delta; 97 osc->last_amp += delta;
98 Blip_set_modified( output );
99 Synth_offset( &this->square_synth, time, delta, output ); 99 Synth_offset( &this->square_synth, time, delta, output );
100 } 100 }
101 101
diff --git a/apps/codecs/libgme/nes_vrc6_apu.h b/apps/codecs/libgme/nes_vrc6_apu.h
index 8f3cbf4629..57b8a42a79 100644
--- a/apps/codecs/libgme/nes_vrc6_apu.h
+++ b/apps/codecs/libgme/nes_vrc6_apu.h
@@ -1,6 +1,6 @@
1// Konami VRC6 sound chip emulator 1// Konami VRC6 sound chip emulator
2 2
3// Nes_Snd_Emu 0.1.8 3// Nes_Snd_Emu 0.2.0-pre
4#ifndef NES_VRC6_APU_H 4#ifndef NES_VRC6_APU_H
5#define NES_VRC6_APU_H 5#define NES_VRC6_APU_H
6 6
@@ -14,7 +14,7 @@ enum { vrc6_addr_step = 0x1000 };
14 14
15struct Vrc6_Osc 15struct Vrc6_Osc
16{ 16{
17 uint8_t regs [vrc6_reg_count]; 17 uint8_t regs [3];
18 struct Blip_Buffer* output; 18 struct Blip_Buffer* output;
19 int delay; 19 int delay;
20 int last_amp; 20 int last_amp;
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
21const char gme_wrong_file_type [] = "Wrong file type for this emulator"; 21const char gme_wrong_file_type [] = "Wrong file type for this emulator";
22long const clock_divisor = 12;
23
24int const stereo = 2; // number of channels for stereo
25int const silence_max = 6; // seconds
26int const silence_threshold = 0x10;
27long const fade_block_size = 512;
28int 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
31int const initial_play_delay = 7; // KikiKaikai needed this to work 24int const initial_play_delay = 7; // KikiKaikai needed this to work
25int const bank_size = 0x1000;
32int const rom_addr = 0x8000; 26int const rom_addr = 0x8000;
33 27
34static void clear_track_vars( struct Nsf_Emu* this ) 28static 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
48static int pcm_read( void* emu, addr_t addr ) 34static 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
74static 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
85static blargg_err_t init_sound( struct Nsf_Emu* this ) 84static 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
182static long clock_rate( struct header_t* this ) 208static 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
187static int play_period( struct header_t* this ) 213static 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
230blargg_err_t Nsf_load( struct Nsf_Emu* this, void* data, long size ) 256blargg_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
432blargg_err_t Nsf_set_sample_rate( struct Nsf_Emu* this, long rate ) 458blargg_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 */
537static 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
554void cpu_write( struct Nsf_Emu* this, addr_t addr, int data ) 564void 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 */
649static 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
670void fill_buf( struct Nsf_Emu* this );
671blargg_err_t Nsf_start_track( struct Nsf_Emu* this, int track ) 659blargg_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
754void run_once( struct Nsf_Emu* this, nes_time_t end ) 732void 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
840static blargg_long msec_to_samples( long sample_rate, blargg_long msec ) 820static 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
847long Track_tell( struct Nsf_Emu* this ) 827int 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
854blargg_err_t Track_seek( struct Nsf_Emu* this, long msec ) 834blargg_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
862blargg_err_t skip_( struct Nsf_Emu* this, long count ); 842blargg_err_t Track_skip( struct Nsf_Emu* this, int count )
863blargg_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
893blargg_err_t play_( struct Nsf_Emu* this, long count, sample_t* out ); 848blargg_err_t skip_( void *emu, int count )
894blargg_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
925void 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 )
932static 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
939static 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
963void emu_play( struct Nsf_Emu* this, long count, sample_t* out ); 867 return skippy_( &this->track_filter, count );
964void 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
979static 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 872void Track_set_fade( struct Nsf_Emu* this, int start_msec, int length_msec )
990void 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
1007blargg_err_t Nsf_play( struct Nsf_Emu* this, long out_count, sample_t* out ) 878blargg_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
1076blargg_err_t play_( struct Nsf_Emu* this, long count, sample_t* out ) 885blargg_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 );
diff --git a/apps/codecs/libgme/nsf_emu.h b/apps/codecs/libgme/nsf_emu.h
index dccfa8c5d5..00bdad4a4e 100644
--- a/apps/codecs/libgme/nsf_emu.h
+++ b/apps/codecs/libgme/nsf_emu.h
@@ -10,6 +10,7 @@
10#include "nes_cpu.h" 10#include "nes_cpu.h"
11#include "nsfe_info.h" 11#include "nsfe_info.h"
12#include "m3u_playlist.h" 12#include "m3u_playlist.h"
13#include "track_filter.h"
13 14
14#ifndef NSF_EMU_APU_ONLY 15#ifndef NSF_EMU_APU_ONLY
15 #include "nes_namco_apu.h" 16 #include "nes_namco_apu.h"
@@ -17,11 +18,11 @@
17 #include "nes_fme7_apu.h" 18 #include "nes_fme7_apu.h"
18 #include "nes_fds_apu.h" 19 #include "nes_fds_apu.h"
19 #include "nes_mmc5_apu.h" 20 #include "nes_mmc5_apu.h"
20 #include "nes_vrc7_apu.h" 21 #ifndef NSF_EMU_NO_VRC7
22 #include "nes_vrc7_apu.h"
23 #endif
21#endif 24#endif
22 25
23typedef short sample_t;
24
25// Sound chip flags 26// Sound chip flags
26enum { 27enum {
27 vrc6_flag = 1 << 0, 28 vrc6_flag = 1 << 0,
@@ -50,8 +51,7 @@ enum { fdsram_size = 0x6000 };
50enum { fdsram_offset = 0x2000 + page_size + 8 }; 51enum { fdsram_offset = 0x2000 + page_size + 8 };
51enum { sram_addr = 0x6000 }; 52enum { sram_addr = 0x6000 };
52enum { unmapped_size= page_size + 8 }; 53enum { unmapped_size= page_size + 8 };
53 54enum { max_voices = 32 };
54enum { buf_size = 2048 };
55 55
56// NSF file header 56// NSF file header
57enum { header_size = 0x80 }; 57enum { header_size = 0x80 };
@@ -82,37 +82,21 @@ struct Nsf_Emu {
82 int play_extra; 82 int play_extra;
83 int play_delay; 83 int play_delay;
84 struct registers_t saved_state; // of interrupted init routine 84 struct registers_t saved_state; // of interrupted init routine
85
86 int track_count;
87 85
88 // general 86 // general
89 int max_initial_silence;
90 int voice_count; 87 int voice_count;
88 int voice_types [32];
91 int mute_mask_; 89 int mute_mask_;
92 int tempo; 90 int tempo;
93 int gain; 91 int gain;
94 92
95 long sample_rate; 93 int sample_rate;
96 94
97 // track-specific 95 // track-specific
96 int track_count;
98 int current_track; 97 int current_track;
99 blargg_long out_time; // number of samples played since start of track
100 blargg_long emu_time; // number of samples emulator has generated since start of track
101 bool emu_track_ended_; // emulator has reached end of track
102 volatile bool track_ended;
103
104 // fading
105 blargg_long fade_start;
106 int fade_step;
107 98
108 // silence detection 99 int clock_rate__;
109 int silence_lookahead; // speed to run emulator when looking ahead for silence
110 bool ignore_silence;
111 long silence_time; // number of samples where most recent silence began
112 long silence_count; // number of samples of silence to play before using buf
113 long buf_remain; // number of samples left in silence buffer
114
115 long clock_rate__;
116 unsigned buf_changed_count; 100 unsigned buf_changed_count;
117 101
118 // M3u Playlist 102 // M3u Playlist
@@ -127,7 +111,9 @@ struct Nsf_Emu {
127 struct Nes_Namco_Apu namco; 111 struct Nes_Namco_Apu namco;
128 struct Nes_Vrc6_Apu vrc6; 112 struct Nes_Vrc6_Apu vrc6;
129 struct Nes_Fme7_Apu fme7; 113 struct Nes_Fme7_Apu fme7;
130 struct Nes_Vrc7_Apu vrc7; 114 #ifndef NSF_EMU_NO_VRC7
115 struct Nes_Vrc7_Apu vrc7;
116 #endif
131 #endif 117 #endif
132 118
133 struct Nes_Cpu cpu; 119 struct Nes_Cpu cpu;
@@ -136,13 +122,15 @@ struct Nsf_Emu {
136 // Header for currently loaded file 122 // Header for currently loaded file
137 struct header_t header; 123 struct header_t header;
138 124
139 struct Stereo_Buffer stereo_buf; 125 struct setup_t tfilter;
126 struct Track_Filter track_filter;
127
128 struct Multi_Buffer stereo_buf;
140 struct Rom_Data rom; 129 struct Rom_Data rom;
141 130
142 // Extended nsf info 131 // Extended nsf info
143 struct Nsfe_Info info; 132 struct Nsfe_Info info;
144 133
145 sample_t buf [buf_size];
146 byte high_ram[fdsram_size + fdsram_offset]; 134 byte high_ram[fdsram_size + fdsram_offset];
147 byte low_ram [low_ram_size]; 135 byte low_ram [low_ram_size];
148}; 136};
@@ -150,18 +138,18 @@ struct Nsf_Emu {
150// Basic functionality (see Gme_File.h for file loading/track info functions) 138// Basic functionality (see Gme_File.h for file loading/track info functions)
151 139
152void Nsf_init( struct Nsf_Emu* this ); 140void Nsf_init( struct Nsf_Emu* this );
153blargg_err_t Nsf_load( struct Nsf_Emu* this, void* data, long size ); 141blargg_err_t Nsf_load_mem( struct Nsf_Emu* this, void* data, long size );
154blargg_err_t Nsf_post_load( struct Nsf_Emu* this ); 142blargg_err_t Nsf_post_load( struct Nsf_Emu* this );
155 143
156// Set output sample rate. Must be called only once before loading file. 144// Set output sample rate. Must be called only once before loading file.
157blargg_err_t Nsf_set_sample_rate( struct Nsf_Emu* this, long sample_rate ); 145blargg_err_t Nsf_set_sample_rate( struct Nsf_Emu* this, int sample_rate );
158 146
159// Start a track, where 0 is the first track. Also clears warning string. 147// Start a track, where 0 is the first track. Also clears warning string.
160blargg_err_t Nsf_start_track( struct Nsf_Emu* this , int ); 148blargg_err_t Nsf_start_track( struct Nsf_Emu* this , int );
161 149
162// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation 150// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
163// errors set warning string, and major errors also end track. 151// errors set warning string, and major errors also end track.
164blargg_err_t Nsf_play( struct Nsf_Emu* this, long count, sample_t* buf ); 152blargg_err_t Nsf_play( struct Nsf_Emu* this, int count, sample_t* buf );
165 153
166void Nsf_clear_playlist( struct Nsf_Emu* this ); 154void Nsf_clear_playlist( struct Nsf_Emu* this );
167void Nsf_disable_playlist( struct Nsf_Emu* this, bool b ); // use clear_playlist() 155void Nsf_disable_playlist( struct Nsf_Emu* this, bool b ); // use clear_playlist()
@@ -169,20 +157,32 @@ void Nsf_disable_playlist( struct Nsf_Emu* this, bool b ); // use clear_playlist
169// Track status/control 157// Track status/control
170 158
171// Number of milliseconds (1000 msec = 1 second) played since beginning of track 159// Number of milliseconds (1000 msec = 1 second) played since beginning of track
172long Track_tell( struct Nsf_Emu* this ); 160int Track_tell( struct Nsf_Emu* this );
173 161
174// Seek to new time in track. Seeking backwards or far forward can take a while. 162// Seek to new time in track. Seeking backwards or far forward can take a while.
175blargg_err_t Track_seek( struct Nsf_Emu* this, long msec ); 163blargg_err_t Track_seek( struct Nsf_Emu* this, int msec );
176 164
177// Skip n samples 165// Skip n samples
178blargg_err_t Track_skip( struct Nsf_Emu* this, long n ); 166blargg_err_t Track_skip( struct Nsf_Emu* this, int n );
179 167
180// Set start time and length of track fade out. Once fade ends track_ended() returns 168// Set start time and length of track fade out. Once fade ends track_ended() returns
181// true. Fade time can be changed while track is playing. 169// true. Fade time can be changed while track is playing.
182void Track_set_fade( struct Nsf_Emu* this, long start_msec, long length_msec ); 170void Track_set_fade( struct Nsf_Emu* this, int start_msec, int length_msec );
171
172// True if a track has reached its end
173static inline bool Track_ended( struct Nsf_Emu* this )
174{
175 return track_ended( &this->track_filter );
176}
177
178// Disables automatic end-of-track detection and skipping of silence at beginning
179static inline void Track_ignore_silence( struct Nsf_Emu* this, bool disable )
180{
181 this->track_filter.silence_ignored_ = disable;
182}
183 183
184// Get track length in milliseconds 184// Get track length in milliseconds
185long Track_length( struct Nsf_Emu* this, int n ); 185int Track_length( struct Nsf_Emu* this, int n );
186 186
187// Sound customization 187// Sound customization
188 188
@@ -217,28 +217,28 @@ bool run_cpu_until( struct Nsf_Emu* this, nes_time_t end );
217 217
218// Sets clocks between calls to play routine to p + 1/2 clock 218// Sets clocks between calls to play routine to p + 1/2 clock
219static inline void set_play_period( struct Nsf_Emu* this, int p ) { this->play_period = p; } 219static inline void set_play_period( struct Nsf_Emu* this, int p ) { this->play_period = p; }
220 220
221// Time play routine will next be called 221// Time play routine will next be called
222static inline nes_time_t play_time( struct Nsf_Emu* this ) { return this->next_play; } 222static inline nes_time_t play_time( struct Nsf_Emu* this ) { return this->next_play; }
223 223
224// Emulates to at least time t. Might emulate a few clocks extra. 224// Emulates to at least time t. Might emulate a few clocks extra.
225void run_until( struct Nsf_Emu* this, nes_time_t t ); 225void run_until( struct Nsf_Emu* this, nes_time_t t );
226 226
227// Runs cpu to at least time t and returns false, or returns true 227// Runs cpu to at least time t and returns false, or returns true
228// if it encounters illegal instruction (halt). 228// if it encounters illegal instruction (halt).
229bool run_cpu_until( struct Nsf_Emu* this, nes_time_t t ); 229bool run_cpu_until( struct Nsf_Emu* this, nes_time_t t );
230 230
231// cpu calls through to these to access memory (except instructions) 231// cpu calls through to these to access memory (except instructions)
232int read_mem( struct Nsf_Emu* this, addr_t ); 232int read_mem( struct Nsf_Emu* this, addr_t );
233void write_mem( struct Nsf_Emu* this, addr_t, int ); 233void write_mem( struct Nsf_Emu* this, addr_t, int );
234 234
235// Address of play routine 235// Address of play routine
236static inline addr_t play_addr( struct Nsf_Emu* this ) { return get_addr( this->header.play_addr ); } 236static inline addr_t play_addr( struct Nsf_Emu* this ) { return get_addr( this->header.play_addr ); }
237 237
238// Same as run_until, except emulation stops for any event (routine returned, 238// Same as run_until, except emulation stops for any event (routine returned,
239// play routine called, illegal instruction). 239// play routine called, illegal instruction).
240void run_once( struct Nsf_Emu* this, nes_time_t ); 240void run_once( struct Nsf_Emu* this, nes_time_t );
241 241
242// Reads byte as cpu would when executing code. Only works for RAM/ROM, 242// Reads byte as cpu would when executing code. Only works for RAM/ROM,
243// NOT I/O like sound chips. 243// NOT I/O like sound chips.
244int read_code( struct Nsf_Emu* this, addr_t addr ); 244int read_code( struct Nsf_Emu* this, addr_t addr );
@@ -248,12 +248,14 @@ static inline byte* sram( struct Nsf_Emu* this ) { return this->high_
248static inline byte* unmapped_code( struct Nsf_Emu* this ) { return &this->high_ram [sram_size]; } 248static inline byte* unmapped_code( struct Nsf_Emu* this ) { return &this->high_ram [sram_size]; }
249 249
250#ifndef NSF_EMU_APU_ONLY 250#ifndef NSF_EMU_APU_ONLY
251static inline int fds_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & fds_flag; } 251 static inline int fds_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & fds_flag; }
252static inline int vrc6_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & vrc6_flag; } 252 static inline int vrc6_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & vrc6_flag; }
253static inline int vrc7_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & vrc7_flag; } 253 #ifndef NSF_EMU_NO_VRC7
254static inline int mmc5_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & mmc5_flag; } 254 static inline int vrc7_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & vrc7_flag; }
255static inline int namco_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & namco_flag; } 255 #endif
256static inline int fme7_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & fme7_flag; } 256 static inline int mmc5_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & mmc5_flag; }
257 static inline int namco_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & namco_flag; }
258 static inline int fme7_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & fme7_flag; }
257#endif 259#endif
258 260
259#endif 261#endif
diff --git a/apps/codecs/libgme/nsfe_info.c b/apps/codecs/libgme/nsfe_info.c
index d22b763173..337b1e580a 100644
--- a/apps/codecs/libgme/nsfe_info.c
+++ b/apps/codecs/libgme/nsfe_info.c
@@ -154,8 +154,8 @@ blargg_err_t Info_load( struct Nsfe_Info* this, void* data, long size, struct Ns
154 byte block_header [2] [4]; 154 byte block_header [2] [4];
155 RETURN_ERR( in_read( block_header, sizeof block_header, data, &offset, size ) ); 155 RETURN_ERR( in_read( block_header, sizeof block_header, data, &offset, size ) );
156 156
157 blargg_long chunk_size = get_le32( block_header [0] ); 157 int chunk_size = get_le32( block_header [0] );
158 blargg_long tag = get_le32( block_header [1] ); 158 int tag = get_le32( block_header [1] );
159 159
160 switch ( tag ) 160 switch ( tag )
161 { 161 {
@@ -168,7 +168,7 @@ blargg_err_t Info_load( struct Nsfe_Info* this, void* data, long size, struct Ns
168 finfo.track_count = 1; 168 finfo.track_count = 1;
169 finfo.first_track = 0; 169 finfo.first_track = 0;
170 170
171 RETURN_ERR( in_read( &finfo, min( chunk_size, (blargg_long) nsfe_info_size ), 171 RETURN_ERR( in_read( &finfo, min( chunk_size, nsfe_info_size ),
172 (char*) data, &offset, size ) ); 172 (char*) data, &offset, size ) );
173 173
174 if ( chunk_size > nsfe_info_size ) 174 if ( chunk_size > nsfe_info_size )
@@ -248,9 +248,9 @@ blargg_err_t Info_load( struct Nsfe_Info* this, void* data, long size, struct Ns
248 return 0; 248 return 0;
249} 249}
250 250
251long Track_length( struct Nsf_Emu* this, int n ) 251int Track_length( struct Nsf_Emu* this, int n )
252{ 252{
253 long length = 0; 253 int length = 0;
254 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) { 254 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
255 struct entry_t* entry = &this->m3u.entries [n]; 255 struct entry_t* entry = &this->m3u.entries [n];
256 length = entry->length; 256 length = entry->length;
diff --git a/apps/codecs/libgme/opl_apu.h b/apps/codecs/libgme/opl_apu.h
index 5ea8185f5f..f24a8d60c2 100644
--- a/apps/codecs/libgme/opl_apu.h
+++ b/apps/codecs/libgme/opl_apu.h
@@ -37,10 +37,10 @@ struct Opl_Apu {
37 37
38blargg_err_t Opl_init( struct Opl_Apu* this, long clock, long rate, blip_time_t period, enum opl_type_t type ); 38blargg_err_t Opl_init( struct Opl_Apu* this, long clock, long rate, blip_time_t period, enum opl_type_t type );
39void Opl_shutdown( struct Opl_Apu* this ); 39void Opl_shutdown( struct Opl_Apu* this );
40 40
41void Opl_reset( struct Opl_Apu* this ); 41void Opl_reset( struct Opl_Apu* this );
42static inline void Opl_volume( struct Opl_Apu* this, int v ) { Synth_volume( &this->synth, v / (4096 * 6) ); } 42static inline void Opl_volume( struct Opl_Apu* this, int v ) { Synth_volume( &this->synth, v / (4096 * 6) ); }
43 43
44static inline void Opl_osc_output( struct Opl_Apu* this, int i, struct Blip_Buffer* buf ) 44static inline void Opl_osc_output( struct Opl_Apu* this, int i, struct Blip_Buffer* buf )
45{ 45{
46#if defined(ROCKBOX) 46#if defined(ROCKBOX)
diff --git a/apps/codecs/libgme/resampler.c b/apps/codecs/libgme/resampler.c
index 837f01ed13..91677cbb8a 100644
--- a/apps/codecs/libgme/resampler.c
+++ b/apps/codecs/libgme/resampler.c
@@ -64,7 +64,7 @@ void Resampler_resize( struct Resampler* this, int pairs )
64 } 64 }
65} 65}
66 66
67void mix_samples( struct Resampler* this, struct Blip_Buffer* blip_buf, sample_t out_ [] ) 67void mix_samples( struct Resampler* this, struct Blip_Buffer* blip_buf, dsample_t out_ [] )
68{ 68{
69 int const bass = BLIP_READER_BASS( *blip_buf ); 69 int const bass = BLIP_READER_BASS( *blip_buf );
70 BLIP_READER_BEGIN( sn, *blip_buf ); 70 BLIP_READER_BEGIN( sn, *blip_buf );
@@ -72,7 +72,7 @@ void mix_samples( struct Resampler* this, struct Blip_Buffer* blip_buf, sample_t
72 int count = this->sample_buf_size >> 1; 72 int count = this->sample_buf_size >> 1;
73 BLIP_READER_ADJ_( sn, count ); 73 BLIP_READER_ADJ_( sn, count );
74 74
75 typedef sample_t stereo_dsample_t [2]; 75 typedef dsample_t stereo_dsample_t [2];
76 stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count; 76 stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count;
77 stereo_dsample_t const* BLARGG_RESTRICT in = 77 stereo_dsample_t const* BLARGG_RESTRICT in =
78 (stereo_dsample_t const*) this->sample_buf + count; 78 (stereo_dsample_t const*) this->sample_buf + count;
@@ -97,14 +97,14 @@ void mix_samples( struct Resampler* this, struct Blip_Buffer* blip_buf, sample_t
97 BLIP_READER_END( sn, *blip_buf ); 97 BLIP_READER_END( sn, *blip_buf );
98} 98}
99 99
100sample_t const* resample_( struct Resampler* this, sample_t** out_, 100dsample_t const* resample_( struct Resampler* this, dsample_t** out_,
101 sample_t const* out_end, sample_t const in [], int in_size ) 101 dsample_t const* out_end, dsample_t const in [], int in_size )
102{ 102{
103 in_size -= write_offset; 103 in_size -= write_offset;
104 if ( in_size > 0 ) 104 if ( in_size > 0 )
105 { 105 {
106 sample_t* BLARGG_RESTRICT out = *out_; 106 dsample_t* BLARGG_RESTRICT out = *out_;
107 sample_t const* const in_end = in + in_size; 107 dsample_t const* const in_end = in + in_size;
108 108
109 int const step = this->step; 109 int const step = this->step;
110 int pos = this->pos; 110 int pos = this->pos;
@@ -135,12 +135,12 @@ sample_t const* resample_( struct Resampler* this, sample_t** out_,
135 return in; 135 return in;
136} 136}
137 137
138static inline int resample_wrapper( struct Resampler* this, sample_t out [], int* out_size, 138static inline int resample_wrapper( struct Resampler* this, dsample_t out [], int* out_size,
139 sample_t const in [], int in_size ) 139 dsample_t const in [], int in_size )
140{ 140{
141 assert( Resampler_rate( this ) ); 141 assert( Resampler_rate( this ) );
142 142
143 sample_t* out_ = out; 143 dsample_t* out_ = out;
144 int result = resample_( this, &out_, out + *out_size, in, in_size ) - in; 144 int result = resample_( this, &out_, out + *out_size, in, in_size ) - in;
145 assert( out_ <= out + *out_size ); 145 assert( out_ <= out + *out_size );
146 assert( result <= in_size ); 146 assert( result <= in_size );
@@ -161,7 +161,7 @@ int skip_input( struct Resampler* this, int count )
161 return count; 161 return count;
162} 162}
163 163
164void play_frame_( struct Resampler* this, struct Blip_Buffer* blip_buf, sample_t* out ) 164void play_frame_( struct Resampler* this, struct Blip_Buffer* blip_buf, dsample_t* out )
165{ 165{
166 int pair_count = this->sample_buf_size >> 1; 166 int pair_count = this->sample_buf_size >> 1;
167 blip_time_t blip_time = Blip_count_clocks( blip_buf, pair_count ); 167 blip_time_t blip_time = Blip_count_clocks( blip_buf, pair_count );
@@ -185,7 +185,7 @@ void play_frame_( struct Resampler* this, struct Blip_Buffer* blip_buf, sample_t
185 Blip_remove_samples( blip_buf, pair_count ); 185 Blip_remove_samples( blip_buf, pair_count );
186} 186}
187 187
188void Resampler_play( struct Resampler* this, int count, sample_t* out, struct Blip_Buffer* blip_buf ) 188void Resampler_play( struct Resampler* this, int count, dsample_t* out, struct Blip_Buffer* blip_buf )
189{ 189{
190 // empty extra buffer 190 // empty extra buffer
191 int remain = this->sample_buf_size - this->buf_pos; 191 int remain = this->sample_buf_size - this->buf_pos;
diff --git a/apps/codecs/libgme/resampler.h b/apps/codecs/libgme/resampler.h
index 1d8f86670b..3f3710a54a 100644
--- a/apps/codecs/libgme/resampler.h
+++ b/apps/codecs/libgme/resampler.h
@@ -7,16 +7,15 @@
7#include "blargg_common.h" 7#include "blargg_common.h"
8#include "multi_buffer.h" 8#include "multi_buffer.h"
9 9
10typedef short sample_t; 10typedef short dsample_t;
11 11
12enum { stereo = 2 };
13enum { max_buf_size = 3960 }; 12enum { max_buf_size = 3960 };
14enum { max_resampler_size = 5942 }; 13enum { max_resampler_size = 5942 };
15enum { write_offset = 8 * stereo }; 14enum { write_offset = 8 * stereo };
16enum { gain_bits = 14 }; 15enum { gain_bits = 14 };
17 16
18struct Resampler { 17struct Resampler {
19 int (*callback)( void*, blip_time_t, int, sample_t* ); 18 int (*callback)( void*, blip_time_t, int, dsample_t* );
20 void* callback_data; 19 void* callback_data;
21 20
22 int sample_buffer_size; 21 int sample_buffer_size;
@@ -34,8 +33,8 @@ struct Resampler {
34 33
35 int rate_; 34 int rate_;
36 35
37 sample_t sample_buf [max_buf_size]; 36 dsample_t sample_buf [max_buf_size];
38 sample_t buf [max_resampler_size]; // Internal resampler 37 dsample_t buf [max_resampler_size]; // Internal resampler
39}; 38};
40 39
41static inline void Resampler_init( struct Resampler* this ) 40static inline void Resampler_init( struct Resampler* this )
@@ -50,9 +49,9 @@ static inline void Resampler_init( struct Resampler* this )
50 49
51blargg_err_t Resampler_reset( struct Resampler* this, int max_pairs ); 50blargg_err_t Resampler_reset( struct Resampler* this, int max_pairs );
52void Resampler_resize( struct Resampler* this, int pairs_per_frame ); 51void Resampler_resize( struct Resampler* this, int pairs_per_frame );
53void Resampler_play( struct Resampler* this, int count, sample_t* out, struct Blip_Buffer* ); 52void Resampler_play( struct Resampler* this, int count, dsample_t* out, struct Blip_Buffer* );
54 53
55static inline void Resampler_set_callback(struct Resampler* this, int (*func)( void*, blip_time_t, int, sample_t* ), void* user_data ) 54static inline void Resampler_set_callback(struct Resampler* this, int (*func)( void*, blip_time_t, int, dsample_t* ), void* user_data )
56{ 55{
57 this->callback = func; 56 this->callback = func;
58 this->callback_data = user_data; 57 this->callback_data = user_data;
diff --git a/apps/codecs/libgme/rom_data.c b/apps/codecs/libgme/rom_data.c
index 5fe3115130..9c36a99d2d 100644
--- a/apps/codecs/libgme/rom_data.c
+++ b/apps/codecs/libgme/rom_data.c
@@ -21,7 +21,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
21blargg_err_t Rom_load( struct Rom_Data* this, const void* data, long size, 21blargg_err_t Rom_load( struct Rom_Data* this, const void* data, long size,
22 int header_size, void* header_out, int fill ) 22 int header_size, void* header_out, int fill )
23{ 23{
24 long file_offset = this->pad_size; 24 int file_offset = this->pad_size;
25 25
26 this->rom_addr = 0; 26 this->rom_addr = 0;
27 this->mask = 0; 27 this->mask = 0;
@@ -43,11 +43,11 @@ blargg_err_t Rom_load( struct Rom_Data* this, const void* data, long size,
43 return 0; 43 return 0;
44} 44}
45 45
46void Rom_set_addr( struct Rom_Data* this, long addr ) 46void Rom_set_addr( struct Rom_Data* this, int addr )
47{ 47{
48 this->rom_addr = addr - this->bank_size - pad_extra; 48 this->rom_addr = addr - this->bank_size - pad_extra;
49 49
50 long rounded = (addr + this->file_size + this->bank_size - 1) / this->bank_size * this->bank_size; 50 int rounded = (addr + this->file_size + this->bank_size - 1) / this->bank_size * this->bank_size;
51 if ( rounded <= 0 ) 51 if ( rounded <= 0 )
52 { 52 {
53 rounded = 0; 53 rounded = 0;
@@ -55,7 +55,7 @@ void Rom_set_addr( struct Rom_Data* this, long addr )
55 else 55 else
56 { 56 {
57 int shift = 0; 57 int shift = 0;
58 unsigned long max_addr = (unsigned long) (rounded - 1); 58 unsigned int max_addr = (unsigned int) (rounded - 1);
59 while ( max_addr >> shift ) 59 while ( max_addr >> shift )
60 shift++; 60 shift++;
61 this->mask = (1L << shift) - 1; 61 this->mask = (1L << shift) - 1;
diff --git a/apps/codecs/libgme/rom_data.h b/apps/codecs/libgme/rom_data.h
index 28b34f2a70..b8bc54cd3f 100644
--- a/apps/codecs/libgme/rom_data.h
+++ b/apps/codecs/libgme/rom_data.h
@@ -20,22 +20,22 @@ enum { max_rom_size = 2 * max_pad_size };
20 20
21struct Rom_Data { 21struct Rom_Data {
22 byte* file_data; 22 byte* file_data;
23 blargg_ulong file_size; 23 unsigned file_size;
24 24
25 blargg_long rom_addr; 25 int rom_addr;
26 blargg_long bank_size; 26 int bank_size;
27 blargg_long rom_size; 27 int rom_size;
28 blargg_ulong pad_size; 28 unsigned pad_size;
29 blargg_long mask; 29 int mask;
30 blargg_long size; // TODO: eliminate 30 int size; // TODO: eliminate
31 blargg_long rsize_; 31 int rsize_;
32 32
33 // Unmapped space 33 // Unmapped space
34 byte unmapped [max_rom_size]; 34 byte unmapped [max_rom_size];
35}; 35};
36 36
37// Initialize rom 37// Initialize rom
38static inline void Rom_init( struct Rom_Data* this, blargg_long bank_size ) 38static inline void Rom_init( struct Rom_Data* this, int bank_size )
39{ 39{
40 this->bank_size = bank_size; 40 this->bank_size = bank_size;
41 this->pad_size = this->bank_size + pad_extra; 41 this->pad_size = this->bank_size + pad_extra;
@@ -47,10 +47,10 @@ static inline void Rom_init( struct Rom_Data* this, blargg_long bank_size )
47blargg_err_t Rom_load( struct Rom_Data* this, const void* data, long size, int header_size, void* header_out, int fill ); 47blargg_err_t Rom_load( struct Rom_Data* this, const void* data, long size, int header_size, void* header_out, int fill );
48 48
49// Set address that file data should start at 49// Set address that file data should start at
50void Rom_set_addr( struct Rom_Data* this, long addr ); 50void Rom_set_addr( struct Rom_Data* this, int addr );
51 51
52// Mask address to nearest power of two greater than size() 52// Mask address to nearest power of two greater than size()
53static inline blargg_long mask_addr( blargg_long addr, blargg_long mask ) 53static inline int mask_addr( int addr, int mask )
54{ 54{
55 #ifdef check 55 #ifdef check
56 check( addr <= mask ); 56 check( addr <= mask );
@@ -59,10 +59,10 @@ static inline blargg_long mask_addr( blargg_long addr, blargg_long mask )
59} 59}
60 60
61// Pointer to page starting at addr. Returns unmapped() if outside data. 61// Pointer to page starting at addr. Returns unmapped() if outside data.
62static inline byte* Rom_at_addr( struct Rom_Data* this, blargg_long addr ) 62static inline byte* Rom_at_addr( struct Rom_Data* this, int addr )
63{ 63{
64 blargg_ulong offset = mask_addr( addr, this->mask ) - this->rom_addr; 64 unsigned offset = mask_addr( addr, this->mask ) - this->rom_addr;
65 if ( offset > (blargg_ulong) (this->rsize_ - this->pad_size) ) 65 if ( offset > (unsigned) (this->rsize_ - this->pad_size) )
66 offset = 0; // unmapped 66 offset = 0; // unmapped
67 67
68 if ( offset < this->pad_size ) return &this->unmapped [offset]; 68 if ( offset < this->pad_size ) return &this->unmapped [offset];
diff --git a/apps/codecs/libgme/sgc_emu.c b/apps/codecs/libgme/sgc_emu.c
index 3c3586611c..a2e6b8df29 100644
--- a/apps/codecs/libgme/sgc_emu.c
+++ b/apps/codecs/libgme/sgc_emu.c
@@ -10,34 +10,19 @@ module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public 12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation, 13License aint with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15 15
16#include "blargg_source.h" 16#include "blargg_source.h"
17 17
18int const osc_count = sms_osc_count + fm_apu_osc_count; 18int const osc_count = sms_osc_count + fm_apu_osc_count;
19 19
20int const stereo = 2; // number of channels for stereo
21int const silence_max = 6; // seconds
22int const silence_threshold = 0x10;
23long const fade_block_size = 512;
24int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
25
26const char gme_wrong_file_type [] = "Wrong file type for this emulator"; 20const char gme_wrong_file_type [] = "Wrong file type for this emulator";
27 21
28static void clear_track_vars( struct Sgc_Emu* this ) 22static void clear_track_vars( struct Sgc_Emu* this )
29{ 23{
30 this->current_track = -1; 24 this->current_track = -1;
31 this->out_time = 0; 25 track_stop( &this->track_filter );
32 this->emu_time = 0;
33 this->emu_track_ended_ = true;
34 this->track_ended = true;
35 this->fade_start = INT_MAX / 2 + 1;
36 this->fade_step = 1;
37 this->silence_time = 0;
38 this->silence_count = 0;
39 this->buf_remain = 0;
40 /* warning(); // clear warning */
41} 26}
42 27
43void Sgc_init( struct Sgc_Emu* this ) 28void Sgc_init( struct Sgc_Emu* this )
@@ -48,12 +33,12 @@ void Sgc_init( struct Sgc_Emu* this )
48 this->mute_mask_ = 0; 33 this->mute_mask_ = 0;
49 this->tempo = (int)FP_ONE_TEMPO; 34 this->tempo = (int)FP_ONE_TEMPO;
50 this->gain = (int)FP_ONE_GAIN; 35 this->gain = (int)FP_ONE_GAIN;
51 this->voice_count = 0;
52 36
53 // defaults 37 // defaults
54 this->max_initial_silence = 2; 38 this->tfilter = *track_get_setup( &this->track_filter );
55 this->silence_lookahead = 6; 39 this->tfilter.max_initial = 2;
56 this->ignore_silence = false; 40 this->tfilter.lookahead = 6;
41 this->track_filter.silence_ignored_ = false;
57 42
58 Sms_apu_init( &this->apu ); 43 Sms_apu_init( &this->apu );
59 Fm_apu_create( &this->fm_apu ); 44 Fm_apu_create( &this->fm_apu );
@@ -62,8 +47,10 @@ void Sgc_init( struct Sgc_Emu* this )
62 Z80_init( &this->cpu ); 47 Z80_init( &this->cpu );
63 48
64 Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) ); 49 Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) );
65 50
66 // Unload 51 // Unload
52 this->voice_count = 0;
53 this->voice_types = 0;
67 clear_track_vars( this ); 54 clear_track_vars( this );
68} 55}
69 56
@@ -95,6 +82,10 @@ blargg_err_t Sgc_load_mem( struct Sgc_Emu* this, const void* data, long size )
95 this->m3u.size = 0; 82 this->m3u.size = 0;
96 this->track_count = this->header.song_count; 83 this->track_count = this->header.song_count;
97 this->voice_count = sega_mapping( this ) ? osc_count : sms_osc_count; 84 this->voice_count = sega_mapping( this ) ? osc_count : sms_osc_count;
85 static int const types [osc_count + 1] = {
86 wave_type+1, wave_type+2, wave_type+3, mixed_type+1, mixed_type+2
87 };
88 this->voice_types = types;
98 89
99 Sms_apu_volume( &this->apu, this->gain ); 90 Sms_apu_volume( &this->apu, this->gain );
100 Fm_apu_volume( &this->fm_apu, this->gain ); 91 Fm_apu_volume( &this->fm_apu, this->gain );
@@ -102,10 +93,10 @@ blargg_err_t Sgc_load_mem( struct Sgc_Emu* this, const void* data, long size )
102 // Setup buffer 93 // Setup buffer
103 this->clock_rate_ = clock_rate( this ); 94 this->clock_rate_ = clock_rate( this );
104 Buffer_clock_rate( &this->stereo_buf, clock_rate( this ) ); 95 Buffer_clock_rate( &this->stereo_buf, clock_rate( this ) );
96 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
105 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); 97 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
106 Sound_set_tempo( this, this->tempo );
107 98
108 // Remute voices 99 Sound_set_tempo( this, this->tempo );
109 Sound_mute_voices( this, this->mute_mask_ ); 100 Sound_mute_voices( this, this->mute_mask_ );
110 return 0; 101 return 0;
111} 102}
@@ -249,7 +240,7 @@ void cpu_write( struct Sgc_Emu* this, addr_t addr, int data )
249 } 240 }
250} 241}
251 242
252blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, long rate ) 243blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, int rate )
253{ 244{
254 require( !this->sample_rate ); // sample rate can't be changed once set 245 require( !this->sample_rate ); // sample rate can't be changed once set
255 Buffer_init( &this->stereo_buf ); 246 Buffer_init( &this->stereo_buf );
@@ -259,6 +250,8 @@ blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, long rate )
259 Buffer_bass_freq( &this->stereo_buf, 80 ); 250 Buffer_bass_freq( &this->stereo_buf, 80 );
260 251
261 this->sample_rate = rate; 252 this->sample_rate = rate;
253 RETURN_ERR( track_init( &this->track_filter, this ) );
254 this->tfilter.max_silence = 6 * stereo * this->sample_rate;
262 return 0; 255 return 0;
263} 256}
264 257
@@ -286,7 +279,7 @@ void Sound_mute_voices( struct Sgc_Emu* this, int mask )
286 } 279 }
287 else 280 else
288 { 281 {
289 struct channel_t ch = Buffer_channel( &this->stereo_buf ); 282 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
290 assert( (ch.center && ch.left && ch.right) || 283 assert( (ch.center && ch.left && ch.right) ||
291 (!ch.center && !ch.left && !ch.right) ); // all or nothing 284 (!ch.center && !ch.left && !ch.right) ); // all or nothing
292 Sound_set_voice( this, i, ch.center, ch.left, ch.right ); 285 Sound_set_voice( this, i, ch.center, ch.left, ch.right );
@@ -306,7 +299,6 @@ void Sound_set_tempo( struct Sgc_Emu* this, int t )
306 this->play_period = (int) ((clock_rate( this ) * FP_ONE_TEMPO) / (this->header.rate ? 50 : 60) / t); 299 this->play_period = (int) ((clock_rate( this ) * FP_ONE_TEMPO) / (this->header.rate ? 50 : 60) / t);
307} 300}
308 301
309void fill_buf( struct Sgc_Emu* this );
310blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track ) 302blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track )
311{ 303{
312 clear_track_vars( this ); 304 clear_track_vars( this );
@@ -383,275 +375,90 @@ blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track )
383 375
384 Buffer_clear( &this->stereo_buf ); 376 Buffer_clear( &this->stereo_buf );
385 377
386 this->emu_track_ended_ = false; 378 // convert filter times to samples
387 this->track_ended = false; 379 struct setup_t s = this->tfilter;
388 380 s.max_initial *= this->sample_rate * stereo;
389 if ( !this->ignore_silence ) 381 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
390 { 382 s.lookahead = 1;
391 // play until non-silence or end of track 383 #endif
392 long end; 384 track_setup( &this->track_filter, &s );
393 for ( end = this->max_initial_silence * stereo * this->sample_rate; this->emu_time < end; ) 385
394 { 386 return track_start( &this->track_filter );
395 fill_buf( this );
396 if ( this->buf_remain | (int) this->emu_track_ended_ )
397 break;
398 }
399
400 this->emu_time = this->buf_remain;
401 this->out_time = 0;
402 this->silence_time = 0;
403 this->silence_count = 0;
404 }
405 /* return track_ended() ? warning() : 0; */
406 return 0;
407} 387}
408 388
409// Tell/Seek 389// Tell/Seek
410 390
411static blargg_long msec_to_samples( blargg_long msec, long sample_rate ) 391static int msec_to_samples( int msec, int sample_rate )
412{ 392{
413 blargg_long sec = msec / 1000; 393 int sec = msec / 1000;
414 msec -= sec * 1000; 394 msec -= sec * 1000;
415 return (sec * sample_rate + msec * sample_rate / 1000) * stereo; 395 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
416} 396}
417 397
418long Track_tell( struct Sgc_Emu* this ) 398int Track_tell( struct Sgc_Emu* this )
419{ 399{
420 blargg_long rate = this->sample_rate * stereo; 400 int rate = this->sample_rate * stereo;
421 blargg_long sec = this->out_time / rate; 401 int sec = track_sample_count( &this->track_filter ) / rate;
422 return sec * 1000 + (this->out_time - sec * rate) * 1000 / rate; 402 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
423} 403}
424 404
425blargg_err_t Track_seek( struct Sgc_Emu* this, long msec ) 405blargg_err_t Track_seek( struct Sgc_Emu* this, int msec )
426{ 406{
427 blargg_long time = msec_to_samples( msec, this->sample_rate ); 407 int time = msec_to_samples( msec, this->sample_rate );
428 if ( time < this->out_time ) 408 if ( time < track_sample_count( &this->track_filter ) )
429 RETURN_ERR( Sgc_start_track( this, this->current_track ) ); 409 RETURN_ERR( Sgc_start_track( this, this->current_track ) );
430 return Track_skip( this, time - this->out_time ); 410 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
431} 411}
432 412
433blargg_err_t skip_( struct Sgc_Emu* this, long count ); 413blargg_err_t Track_skip( struct Sgc_Emu* this, int count )
434blargg_err_t Track_skip( struct Sgc_Emu* this, long count )
435{ 414{
436 require( this->current_track >= 0 ); // start_track() must have been called already 415 require( this->current_track >= 0 ); // start_track() must have been called already
437 this->out_time += count; 416 return track_skip( &this->track_filter, count );
438
439 // remove from silence and buf first
440 {
441 long n = min( count, this->silence_count );
442 this->silence_count -= n;
443 count -= n;
444
445 n = min( count, this->buf_remain );
446 this->buf_remain -= n;
447 count -= n;
448 }
449
450 if ( count && !this->emu_track_ended_ )
451 {
452 this->emu_time += count;
453
454 // End track if error
455 if ( skip_( this, count ) ) {
456 this->emu_track_ended_ = true;
457 }
458 }
459
460 if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended
461 this->track_ended |= this->emu_track_ended_;
462
463 return 0;
464} 417}
465 418
466blargg_err_t play_( struct Sgc_Emu* this, long count, sample_t* out ); 419blargg_err_t skip_( void* emu, int count )
467blargg_err_t skip_( struct Sgc_Emu* this, long count )
468{ 420{
421 struct Sgc_Emu* this = (struct Sgc_Emu*) emu;
422
469 // for long skip, mute sound 423 // for long skip, mute sound
470 const long threshold = 30000; 424 const int threshold = 32768;
471 if ( count > threshold ) 425 if ( count > threshold )
472 { 426 {
473 int saved_mute = this->mute_mask_; 427 int saved_mute = this->mute_mask_;
474 Sound_mute_voices( this, ~0 ); 428 Sound_mute_voices( this, ~0 );
475
476 while ( count > threshold / 2 && !this->emu_track_ended_ )
477 {
478 RETURN_ERR( play_( this, buf_size, this->buf ) );
479 count -= buf_size;
480 }
481
482 Sound_mute_voices( this, saved_mute );
483 }
484
485 while ( count && !this->emu_track_ended_ )
486 {
487 long n = buf_size;
488 if ( n > count )
489 n = count;
490 count -= n;
491 RETURN_ERR( play_( this, n, this->buf ) );
492 }
493 return 0;
494}
495
496// Fading
497
498void Track_set_fade( struct Sgc_Emu* this, long start_msec, long length_msec )
499{
500 this->fade_step = this->sample_rate * length_msec / (fade_block_size * fade_shift * 1000 / stereo);
501 this->fade_start = msec_to_samples( start_msec, this->sample_rate );
502}
503
504// unit / pow( 2.0, (double) x / step )
505static int int_log( blargg_long x, int step, int unit )
506{
507 int shift = x / step;
508 int fraction = (x - shift * step) * unit / step;
509 return ((unit - fraction) + (fraction >> 1)) >> shift;
510}
511
512static void handle_fade( struct Sgc_Emu* this, long out_count, sample_t* out )
513{
514 int i;
515 for ( i = 0; i < out_count; i += fade_block_size )
516 {
517 int const shift = 14;
518 int const unit = 1 << shift;
519 int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size,
520 this->fade_step, unit );
521 if ( gain < (unit >> fade_shift) )
522 this->track_ended = this->emu_track_ended_ = true;
523
524 sample_t* io = &out [i];
525 int count;
526 for ( count = min( fade_block_size, out_count - i ); count; --count )
527 {
528 *io = (sample_t) ((*io * gain) >> shift);
529 ++io;
530 }
531 }
532}
533 429
534// Silence detection 430 int n = count - threshold/2;
431 n &= ~(2048-1); // round to multiple of 2048
432 count -= n;
433 RETURN_ERR( skippy_( &this->track_filter, n ) );
535 434
536static void emu_play( struct Sgc_Emu* this, long count, sample_t* out ) 435 Sound_mute_voices( this, saved_mute );
537{
538 check( this->current_track_ >= 0 );
539 this->emu_time += count;
540 if ( this->current_track >= 0 && !this->emu_track_ended_ ) {
541 // End track if error
542 if ( play_( this, count, out ) )
543 this->emu_track_ended_ = true;
544 } 436 }
545 else
546 memset( out, 0, count * sizeof *out );
547}
548 437
549// number of consecutive silent samples at end 438 return skippy_( &this->track_filter, count );
550static long count_silence( sample_t* begin, long size )
551{
552 sample_t first = *begin;
553 *begin = silence_threshold; // sentinel
554 sample_t* p = begin + size;
555 while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
556 *begin = first;
557 return size - (p - begin);
558} 439}
559 440
560// fill internal buffer and check it for silence 441void Track_set_fade( struct Sgc_Emu* this, int start_msec, int length_msec )
561void fill_buf( struct Sgc_Emu* this )
562{ 442{
563 assert( !this->buf_remain ); 443 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
564 if ( !this->emu_track_ended_ ) 444 length_msec * this->sample_rate / (1000 / stereo) );
565 {
566 emu_play( this, buf_size, this->buf );
567 long silence = count_silence( this->buf, buf_size );
568 if ( silence < buf_size )
569 {
570 this->silence_time = this->emu_time - silence;
571 this->buf_remain = buf_size;
572 return;
573 }
574 }
575 this->silence_count += buf_size;
576} 445}
577 446
578blargg_err_t Sgc_play( struct Sgc_Emu* this, long out_count, sample_t* out ) 447blargg_err_t Sgc_play( struct Sgc_Emu* this, int out_count, sample_t* out )
579{ 448{
580 if ( this->track_ended ) 449 require( this->current_track >= 0 );
581 { 450 require( out_count % stereo == 0 );
582 memset( out, 0, out_count * sizeof *out ); 451 return track_play( &this->track_filter, out_count, out );
583 }
584 else
585 {
586 require( this->current_track >= 0 );
587 require( out_count % stereo == 0 );
588
589 assert( this->emu_time >= this->out_time );
590
591 // prints nifty graph of how far ahead we are when searching for silence
592 //debug_printf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" );
593
594 long pos = 0;
595 if ( this->silence_count )
596 {
597 // during a run of silence, run emulator at >=2x speed so it gets ahead
598 long ahead_time = this->silence_lookahead * (this->out_time + out_count - this->silence_time) + this->silence_time;
599 while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) )
600 fill_buf( this );
601
602 // fill with silence
603 pos = min( this->silence_count, out_count );
604 memset( out, 0, pos * sizeof *out );
605 this->silence_count -= pos;
606
607 if ( this->emu_time - this->silence_time > silence_max * stereo * this->sample_rate )
608 {
609 this->track_ended = this->emu_track_ended_ = true;
610 this->silence_count = 0;
611 this->buf_remain = 0;
612 }
613 }
614
615 if ( this->buf_remain )
616 {
617 // empty silence buf
618 long n = min( this->buf_remain, out_count - pos );
619 memcpy( &out [pos], this->buf + (buf_size - this->buf_remain), n * sizeof *out );
620 this->buf_remain -= n;
621 pos += n;
622 }
623
624 // generate remaining samples normally
625 long remain = out_count - pos;
626 if ( remain )
627 {
628 emu_play( this, remain, out + pos );
629 this->track_ended |= this->emu_track_ended_;
630
631 if ( !this->ignore_silence || this->out_time > this->fade_start )
632 {
633 // check end for a new run of silence
634 long silence = count_silence( out + pos, remain );
635 if ( silence < remain )
636 this->silence_time = this->emu_time - silence;
637
638 if ( this->emu_time - this->silence_time >= buf_size )
639 fill_buf( this ); // cause silence detection on next play()
640 }
641 }
642
643 if ( this->out_time > this->fade_start )
644 handle_fade( this, out_count, out );
645 }
646 this->out_time += out_count;
647 return 0;
648} 452}
649 453
650blargg_err_t play_( struct Sgc_Emu* this, long count, sample_t* out ) 454blargg_err_t play_( void* emu, int count, sample_t out [] )
651{ 455{
652 long remain = count; 456 struct Sgc_Emu* this = (struct Sgc_Emu*) emu;
457
458 int remain = count;
653 while ( remain ) 459 while ( remain )
654 { 460 {
461 Buffer_disable_immediate_removal( &this->stereo_buf );
655 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain ); 462 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
656 if ( remain ) 463 if ( remain )
657 { 464 {
diff --git a/apps/codecs/libgme/sgc_emu.h b/apps/codecs/libgme/sgc_emu.h
index 779ef2d923..6595c02daf 100644
--- a/apps/codecs/libgme/sgc_emu.h
+++ b/apps/codecs/libgme/sgc_emu.h
@@ -12,16 +12,14 @@
12#include "sms_fm_apu.h" 12#include "sms_fm_apu.h"
13#include "sms_apu.h" 13#include "sms_apu.h"
14#include "m3u_playlist.h" 14#include "m3u_playlist.h"
15#include "track_filter.h"
15 16
16typedef short sample_t;
17typedef struct Z80_Cpu Sgc_Cpu; 17typedef struct Z80_Cpu Sgc_Cpu;
18 18
19enum { buf_size = 2048 };
20
21// SGC file header 19// SGC file header
22enum { header_size = 0xA0 }; 20enum { header_size = 0xA0 };
23struct header_t 21struct header_t
24{ 22{
25 char tag [4]; // "SGC\x1A" 23 char tag [4]; // "SGC\x1A"
26 byte vers; // 0x01 24 byte vers; // 0x01
27 byte rate; // 0=NTSC 1=PAL 25 byte rate; // 0=NTSC 1=PAL
@@ -48,12 +46,11 @@ struct header_t
48static inline bool valid_tag( struct header_t* h ) 46static inline bool valid_tag( struct header_t* h )
49{ 47{
50 return 0 == memcmp( h->tag, "SGC\x1A", 4 ); 48 return 0 == memcmp( h->tag, "SGC\x1A", 4 );
51} 49}
52
53static inline int effect_count( struct header_t* h ) { return h->last_effect ? h->last_effect - h->first_effect + 1 : 0; }
54 50
51static inline int effect_count( struct header_t* h ) { return h->last_effect ? h->last_effect - h->first_effect + 1 : 0; }
55 52
56struct Sgc_Emu { 53struct Sgc_Emu {
57 bool fm_accessed; 54 bool fm_accessed;
58 55
59 cpu_time_t play_period; 56 cpu_time_t play_period;
@@ -65,40 +62,28 @@ struct Sgc_Emu {
65 62
66 // general 63 // general
67 int voice_count; 64 int voice_count;
65 int const* voice_types;
68 int mute_mask_; 66 int mute_mask_;
69 int tempo; 67 int tempo;
70 int gain; 68 int gain;
71 69
72 long sample_rate; 70 int sample_rate;
73 71
74 // track-specific 72 // track-specific
75 volatile bool track_ended;
76 int current_track; 73 int current_track;
77 int track_count; 74 int track_count;
78 blargg_long out_time; // number of samples played since start of track 75
79 blargg_long emu_time; // number of samples emulator has generated since start of track 76 int clock_rate_;
80 bool emu_track_ended_; // emulator has reached end of track
81
82 // fading
83 blargg_long fade_start;
84 int fade_step;
85
86 // silence detection
87 bool ignore_silence;
88 int max_initial_silence;
89 int silence_lookahead; // speed to run emulator when looking ahead for silence
90 long silence_time; // number of samples where most recent silence began
91 long silence_count; // number of samples of silence to play before using buf
92 long buf_remain; // number of samples left in silence buffer
93
94 long clock_rate_;
95 unsigned buf_changed_count; 77 unsigned buf_changed_count;
96 78
97 // M3u Playlist 79 // M3u Playlist
98 struct M3u_Playlist m3u; 80 struct M3u_Playlist m3u;
81 struct header_t header;
99 82
100 sample_t buf [buf_size]; 83 struct setup_t tfilter;
101 struct Stereo_Buffer stereo_buf; 84 struct Track_Filter track_filter;
85
86 struct Multi_Buffer stereo_buf;
102 87
103 struct Sms_Apu apu; 88 struct Sms_Apu apu;
104 struct Sms_Fm_Apu fm_apu; 89 struct Sms_Fm_Apu fm_apu;
@@ -106,12 +91,11 @@ struct Sgc_Emu {
106 Sgc_Cpu cpu; 91 Sgc_Cpu cpu;
107 92
108 // large items 93 // large items
109 struct header_t header;
110 struct Rom_Data rom; 94 struct Rom_Data rom;
111 byte vectors [page_size + page_padding]; 95 byte vectors [page_size + page_padding];
96 byte unmapped_write [0x4000];
112 byte ram [0x2000 + page_padding]; 97 byte ram [0x2000 + page_padding];
113 byte ram2 [0x4000 + page_padding]; 98 byte ram2 [0x4000 + page_padding];
114 byte unmapped_write [0x4000];
115}; 99};
116 100
117// Basic functionality (see Gme_File.h for file loading/track info functions) 101// Basic functionality (see Gme_File.h for file loading/track info functions)
@@ -119,41 +103,53 @@ struct Sgc_Emu {
119void Sgc_init( struct Sgc_Emu* this ); 103void Sgc_init( struct Sgc_Emu* this );
120 104
121blargg_err_t Sgc_load_mem( struct Sgc_Emu* this, const void* data, long size ); 105blargg_err_t Sgc_load_mem( struct Sgc_Emu* this, const void* data, long size );
122 106
123static inline int clock_rate( struct Sgc_Emu* this ) { return this->header.rate ? 3546893 : 3579545; } 107static inline int clock_rate( struct Sgc_Emu* this ) { return this->header.rate ? 3546893 : 3579545; }
124 108
125// 0x2000 bytes 109// 0x2000 bytes
126static inline void set_coleco_bios( struct Sgc_Emu* this, void* p ) { this->coleco_bios = p; } 110static inline void set_coleco_bios( struct Sgc_Emu* this, void* p ) { this->coleco_bios = p; }
127 111
128// Set output sample rate. Must be called only once before loading file. 112// Set output sample rate. Must be called only once before loading file.
129blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, long sample_rate ); 113blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, int sample_rate );
130 114
131// Start a track, where 0 is the first track. Also clears warning string. 115// Start a track, where 0 is the first track. Also clears warning string.
132blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track ); 116blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track );
133 117
134// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation 118// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
135// errors set warning string, and major errors also end track. 119// errors set warning string, and major errors also end track.
136blargg_err_t Sgc_play( struct Sgc_Emu* this, long count, sample_t* buf ); 120blargg_err_t Sgc_play( struct Sgc_Emu* this, int count, sample_t* buf );
137 121
138// Track status/control 122// Track status/control
139 123
140// Number of milliseconds (1000 msec = 1 second) played since beginning of track 124// Number of milliseconds (1000 msec = 1 second) played since beginning of track
141long Track_tell( struct Sgc_Emu* this ); 125int Track_tell( struct Sgc_Emu* this );
142 126
143// Seek to new time in track. Seeking backwards or far forward can take a while. 127// Seek to new time in track. Seeking backwards or far forward can take a while.
144blargg_err_t Track_seek( struct Sgc_Emu* this, long msec ); 128blargg_err_t Track_seek( struct Sgc_Emu* this, int msec );
145 129
146// Skip n samples 130// Skip n samples
147blargg_err_t Track_skip( struct Sgc_Emu* this, long n ); 131blargg_err_t Track_skip( struct Sgc_Emu* this, int n );
148 132
149// Set start time and length of track fade out. Once fade ends track_ended() returns 133// Set start time and length of track fade out. Once fade ends track_ended() returns
150// true. Fade time can be changed while track is playing. 134// true. Fade time can be changed while track is playing.
151void Track_set_fade( struct Sgc_Emu* this, long start_msec, long length_msec ); 135void Track_set_fade( struct Sgc_Emu* this, int start_msec, int length_msec );
136
137// True if a track has reached its end
138static inline bool Track_ended( struct Sgc_Emu* this )
139{
140 return track_ended( &this->track_filter );
141}
142
143// Disables automatic end-of-track detection and skipping of silence at beginning
144static inline void Track_ignore_silence( struct Sgc_Emu* this, bool disable )
145{
146 this->track_filter.silence_ignored_ = disable;
147}
152 148
153// Get track length in milliseconds 149// Get track length in milliseconds
154static inline long Track_get_length( struct Sgc_Emu* this, int n ) 150static inline int Track_get_length( struct Sgc_Emu* this, int n )
155{ 151{
156 long length = 120 * 1000; /* 2 minutes */ 152 int length = 120 * 1000; /* 2 minutes */
157 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) { 153 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
158 struct entry_t* entry = &this->m3u.entries [n]; 154 struct entry_t* entry = &this->m3u.entries [n];
159 length = entry->length; 155 length = entry->length;
diff --git a/apps/codecs/libgme/sms_apu.c b/apps/codecs/libgme/sms_apu.c
index 965e4836c4..379fcf1cbf 100644
--- a/apps/codecs/libgme/sms_apu.c
+++ b/apps/codecs/libgme/sms_apu.c
@@ -158,9 +158,7 @@ static void run_until( struct Sms_Apu* this, blip_time_t end_time )
158 if ( delta ) 158 if ( delta )
159 { 159 {
160 osc->last_amp = amp; 160 osc->last_amp = amp;
161 /* norm_synth.offset( last_time, delta, out ); */
162 Synth_offset( &this->synth, this->last_time, delta, out ); 161 Synth_offset( &this->synth, this->last_time, delta, out );
163 /* out->set_modified(); */
164 Blip_set_modified( out ); 162 Blip_set_modified( out );
165 } 163 }
166 } 164 }
@@ -200,7 +198,6 @@ static void run_until( struct Sms_Apu* this, blip_time_t end_time )
200 do 198 do
201 { 199 {
202 delta = -delta; 200 delta = -delta;
203 /* norm_synth.offset( time, delta, out ); */
204 Synth_offset( &this->synth, time, delta, out ); 201 Synth_offset( &this->synth, time, delta, out );
205 time += period; 202 time += period;
206 } 203 }
@@ -218,7 +215,6 @@ static void run_until( struct Sms_Apu* this, blip_time_t end_time )
218 if ( changed & 2 ) // true if bits 0 and 1 differ 215 if ( changed & 2 ) // true if bits 0 and 1 differ
219 { 216 {
220 delta = -delta; 217 delta = -delta;
221 /* fast_synth.offset_inline( time, delta, out ); */
222 Synth_offset_inline( &this->synth, time, delta, out ); 218 Synth_offset_inline( &this->synth, time, delta, out );
223 } 219 }
224 time += period; 220 time += period;
diff --git a/apps/codecs/libgme/sms_apu.h b/apps/codecs/libgme/sms_apu.h
index f887dc611e..6dd65591ce 100644
--- a/apps/codecs/libgme/sms_apu.h
+++ b/apps/codecs/libgme/sms_apu.h
@@ -44,10 +44,10 @@ void Sms_apu_set_output( struct Sms_Apu* this, int i, struct Blip_Buffer* center
44 44
45// Emulates to time t, then writes data to Game Gear left/right assignment byte 45// Emulates to time t, then writes data to Game Gear left/right assignment byte
46void Sms_apu_write_ggstereo( struct Sms_Apu* this, blip_time_t t, int data ); 46void Sms_apu_write_ggstereo( struct Sms_Apu* this, blip_time_t t, int data );
47 47
48// Emulates to time t, then writes data 48// Emulates to time t, then writes data
49void Sms_apu_write_data( struct Sms_Apu* this, blip_time_t t, int data ); 49void Sms_apu_write_data( struct Sms_Apu* this, blip_time_t t, int data );
50 50
51// Emulates to time t, then subtracts t from the current time. 51// Emulates to time t, then subtracts t from the current time.
52// OK if previous write call had time slightly after t. 52// OK if previous write call had time slightly after t.
53void Sms_apu_end_frame( struct Sms_Apu* this, blip_time_t t ); 53void Sms_apu_end_frame( struct Sms_Apu* this, blip_time_t t );
diff --git a/apps/codecs/libgme/sms_fm_apu.h b/apps/codecs/libgme/sms_fm_apu.h
index cf8cd6c5cb..00bc2b409c 100644
--- a/apps/codecs/libgme/sms_fm_apu.h
+++ b/apps/codecs/libgme/sms_fm_apu.h
@@ -25,19 +25,19 @@ void Fm_apu_create( struct Sms_Fm_Apu* this );
25 25
26static inline bool Fm_apu_supported( void ) { return Ym2413_supported(); } 26static inline bool Fm_apu_supported( void ) { return Ym2413_supported(); }
27blargg_err_t Fm_apu_init( struct Sms_Fm_Apu* this, int clock_rate, int sample_rate ); 27blargg_err_t Fm_apu_init( struct Sms_Fm_Apu* this, int clock_rate, int sample_rate );
28 28
29static inline void Fm_apu_set_output( struct Sms_Fm_Apu* this, struct Blip_Buffer* b ) 29static inline void Fm_apu_set_output( struct Sms_Fm_Apu* this, struct Blip_Buffer* b )
30{ 30{
31 this->output_ = b; 31 this->output_ = b;
32} 32}
33 33
34static inline void Fm_apu_volume( struct Sms_Fm_Apu* this, int v ) { Synth_volume( &this->synth, (v*2) / 5 / 4096 ); } 34static inline void Fm_apu_volume( struct Sms_Fm_Apu* this, int v ) { Synth_volume( &this->synth, (v*2) / 5 / 4096 ); }
35 35
36void Fm_apu_reset( struct Sms_Fm_Apu* this ); 36void Fm_apu_reset( struct Sms_Fm_Apu* this );
37 37
38static inline void Fm_apu_write_addr( struct Sms_Fm_Apu* this, int data ) { this->addr = data; } 38static inline void Fm_apu_write_addr( struct Sms_Fm_Apu* this, int data ) { this->addr = data; }
39void Fm_apu_write_data( struct Sms_Fm_Apu* this, blip_time_t, int data ); 39void Fm_apu_write_data( struct Sms_Fm_Apu* this, blip_time_t, int data );
40 40
41void Fm_apu_end_frame( struct Sms_Fm_Apu* this, blip_time_t t ); 41void Fm_apu_end_frame( struct Sms_Fm_Apu* this, blip_time_t t );
42 42
43#endif 43#endif
diff --git a/apps/codecs/libgme/track_filter.c b/apps/codecs/libgme/track_filter.c
new file mode 100644
index 0000000000..f468a8c4b6
--- /dev/null
+++ b/apps/codecs/libgme/track_filter.c
@@ -0,0 +1,294 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "track_filter.h"
4
5/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "blargg_source.h"
17
18int const fade_block_size = 512;
19int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
20int const silence_threshold = 8;
21
22void track_create( struct Track_Filter* this )
23{
24 this->emu_ = NULL;
25 this->setup_.max_initial = 0;
26 this->setup_.lookahead = 0;
27 this->setup_.max_silence = indefinite_count;
28 this->silence_ignored_ = false;
29 track_stop( this );
30}
31
32blargg_err_t track_init( struct Track_Filter* this, void* emu )
33{
34 this->emu_ = emu;
35 return 0;
36}
37
38void clear_time_vars( struct Track_Filter* this )
39{
40 this->emu_time = this->buf_remain;
41 this->out_time = 0;
42 this->silence_time = 0;
43 this->silence_count = 0;
44}
45
46void track_stop( struct Track_Filter* this )
47{
48 this->emu_track_ended_ = true;
49 this->track_ended_ = true;
50 this->fade_start = indefinite_count;
51 this->fade_step = 1;
52 this->buf_remain = 0;
53 this->emu_error = NULL;
54 clear_time_vars( this );
55}
56
57blargg_err_t track_start( struct Track_Filter* this )
58{
59 this->emu_error = NULL;
60 track_stop( this );
61
62 this->emu_track_ended_ = false;
63 this->track_ended_ = false;
64
65 if ( !this->silence_ignored_ )
66 {
67 // play until non-silence or end of track
68 while ( this->emu_time < this->setup_.max_initial )
69 {
70 fill_buf( this );
71 if ( this->buf_remain | this->emu_track_ended_ )
72 break;
73 }
74 }
75
76 clear_time_vars( this );
77 return this->emu_error;
78}
79
80void end_track_if_error( struct Track_Filter* this, blargg_err_t err )
81{
82 if ( err )
83 {
84 this->emu_error = err;
85 this->emu_track_ended_ = true;
86 }
87}
88
89blargg_err_t track_skip( struct Track_Filter* this, int count )
90{
91 this->emu_error = NULL;
92 this->out_time += count;
93
94 // remove from silence and buf first
95 {
96 int n = min( count, this->silence_count );
97 this->silence_count -= n;
98 count -= n;
99
100 n = min( count, this->buf_remain );
101 this->buf_remain -= n;
102 count -= n;
103 }
104
105 if ( count && !this->emu_track_ended_ )
106 {
107 this->emu_time += count;
108 this->silence_time = this->emu_time; // would otherwise be invalid
109 end_track_if_error( this, skip_( this->emu_, count ) );
110 }
111
112 if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended
113 this->track_ended_ |= this->emu_track_ended_;
114
115 return this->emu_error;
116}
117
118blargg_err_t skippy_( struct Track_Filter* this, int count )
119{
120 while ( count && !this->emu_track_ended_ )
121 {
122 int n = buf_size;
123 if ( n > count )
124 n = count;
125 count -= n;
126 RETURN_ERR( play_( this->emu_, n, this->buf ) );
127 }
128 return 0;
129}
130
131// Fading
132
133void track_set_fade( struct Track_Filter* this, int start, int length )
134{
135 this->fade_start = start;
136 this->fade_step = length / (fade_block_size * fade_shift);
137 if ( this->fade_step < 1 )
138 this->fade_step = 1;
139}
140
141bool is_fading( struct Track_Filter* this )
142{
143 return this->out_time >= this->fade_start && this->fade_start != indefinite_count;
144}
145
146// unit / pow( 2.0, (double) x / step )
147static int int_log( int x, int step, int unit )
148{
149 int shift = x / step;
150 int fraction = (x - shift * step) * unit / step;
151 return ((unit - fraction) + (fraction >> 1)) >> shift;
152}
153
154void handle_fade( struct Track_Filter* this, sample_t out [], int out_count )
155{
156 int i;
157 for ( i = 0; i < out_count; i += fade_block_size )
158 {
159 int const shift = 14;
160 int const unit = 1 << shift;
161 int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size,
162 this->fade_step, unit );
163 if ( gain < (unit >> fade_shift) )
164 this->track_ended_ = this->emu_track_ended_ = true;
165
166 sample_t* io = &out [i];
167 for ( int count = min( fade_block_size, out_count - i ); count; --count )
168 {
169 *io = (sample_t) ((*io * gain) >> shift);
170 ++io;
171 }
172 }
173}
174
175// Silence detection
176
177void emu_play( struct Track_Filter* this, sample_t out [], int count )
178{
179 this->emu_time += count;
180 if ( !this->emu_track_ended_ )
181 end_track_if_error( this, play_( this->emu_, count, out ) );
182 else
183 memset( out, 0, count * sizeof *out );
184}
185
186// number of consecutive silent samples at end
187static int count_silence( sample_t begin [], int size )
188{
189 sample_t first = *begin;
190 *begin = silence_threshold * 2; // sentinel
191 sample_t* p = begin + size;
192 while ( (unsigned) (*--p + silence_threshold) <= (unsigned) silence_threshold * 2 ) { }
193 *begin = first;
194 return size - (p - begin);
195}
196
197// fill internal buffer and check it for silence
198void fill_buf( struct Track_Filter* this )
199{
200 assert( !this->buf_remain );
201 if ( !this->emu_track_ended_ )
202 {
203 emu_play( this, this->buf, buf_size );
204 int silence = count_silence( this->buf, buf_size );
205 if ( silence < buf_size )
206 {
207 this->silence_time = this->emu_time - silence;
208 this->buf_remain = buf_size;
209 return;
210 }
211 }
212 this->silence_count += buf_size;
213}
214
215blargg_err_t track_play( struct Track_Filter* this, int out_count, sample_t out [] )
216{
217 this->emu_error = NULL;
218 if ( this->track_ended_ )
219 {
220 memset( out, 0, out_count * sizeof *out );
221 }
222 else
223 {
224 assert( this->emu_time >= this->out_time );
225
226 // prints nifty graph of how far ahead we are when searching for silence
227 //dprintf( "%*s \n", int ((emu_time - out_time) * 7 / 44100), "*" );
228
229 // use any remaining silence samples
230 int pos = 0;
231 if ( this->silence_count )
232 {
233 if ( !this->silence_ignored_ )
234 {
235 // during a run of silence, run emulator at >=2x speed so it gets ahead
236 int ahead_time = this->setup_.lookahead * (this->out_time + out_count - this->silence_time) +
237 this->silence_time;
238 while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) )
239 fill_buf( this );
240
241 // end track if sufficient silence has been found
242 if ( this->emu_time - this->silence_time > this->setup_.max_silence )
243 {
244 this->track_ended_ = this->emu_track_ended_ = true;
245 this->silence_count = out_count;
246 this->buf_remain = 0;
247 }
248 }
249
250 // fill from remaining silence
251 pos = min( this->silence_count, out_count );
252 memset( out, 0, pos * sizeof *out );
253 this->silence_count -= pos;
254 }
255
256 // use any remaining samples from buffer
257 if ( this->buf_remain )
258 {
259 int n = min( this->buf_remain, (int) (out_count - pos) );
260 memcpy( out + pos, this->buf + (buf_size - this->buf_remain), n * sizeof *out );
261 this->buf_remain -= n;
262 pos += n;
263 }
264
265 // generate remaining samples normally
266 int remain = out_count - pos;
267 if ( remain )
268 {
269 emu_play( this, out + pos, remain );
270 this->track_ended_ |= this->emu_track_ended_;
271
272 if ( this->silence_ignored_ && !is_fading( this ) )
273 {
274 // if left unupdated, ahead_time could become too large
275 this->silence_time = this->emu_time;
276 }
277 else
278 {
279 // check end for a new run of silence
280 int silence = count_silence( out + pos, remain );
281 if ( silence < remain )
282 this->silence_time = this->emu_time - silence;
283
284 if ( this->emu_time - this->silence_time >= buf_size )
285 fill_buf( this ); // cause silence detection on next play()
286 }
287 }
288
289 if ( is_fading( this ) )
290 handle_fade( this, out, out_count );
291 }
292 this->out_time += out_count;
293 return this->emu_error;
294}
diff --git a/apps/codecs/libgme/track_filter.h b/apps/codecs/libgme/track_filter.h
new file mode 100644
index 0000000000..35049b91bb
--- /dev/null
+++ b/apps/codecs/libgme/track_filter.h
@@ -0,0 +1,90 @@
1// Removes silence from beginning of track, fades end of track. Also looks ahead
2// for excessive silence, and if found, ends track.
3
4// Game_Music_Emu 0.6-pre
5#ifndef TRACK_FILTER_H
6#define TRACK_FILTER_H
7
8#include "blargg_common.h"
9
10typedef short sample_t;
11typedef int sample_count_t;
12
13enum { indefinite_count = INT_MAX/2 + 1 };
14enum { buf_size = 2048 };
15
16struct setup_t {
17 sample_count_t max_initial; // maximum silence to strip from beginning of track
18 sample_count_t max_silence; // maximum silence in middle of track without it ending
19 int lookahead; // internal speed when looking ahead for silence (2=200% etc.)
20};
21
22struct Track_Filter {
23 void* emu_;
24 struct setup_t setup_;
25 const char* emu_error;
26 bool silence_ignored_;
27
28 // Timing
29 int out_time; // number of samples played since start of track
30 int emu_time; // number of samples emulator has generated since start of track
31 int emu_track_ended_; // emulator has reached end of track
32 volatile int track_ended_;
33
34 // Fading
35 int fade_start;
36 int fade_step;
37
38 // Silence detection
39 int silence_time; // absolute number of samples where most recent silence began
40 int silence_count; // number of samples of silence to play before using buf
41 int buf_remain; // number of samples left in silence buffer
42 sample_t buf [buf_size];
43};
44
45// Initializes filter. Must be done once before using object.
46blargg_err_t track_init( struct Track_Filter* this, void* );
47void track_create( struct Track_Filter* this );
48
49// Gets/sets setup
50static inline struct setup_t const* track_get_setup( struct Track_Filter* this ) { return &this->setup_; }
51static inline void track_setup( struct Track_Filter* this, struct setup_t const* s ) { this->setup_ = *s; }
52
53// Disables automatic end-of-track detection and skipping of silence at beginning
54static inline void track_ignore_silence( struct Track_Filter* this, bool disable ) { this->silence_ignored_ = disable; }
55
56// Clears state and skips initial silence in track
57blargg_err_t track_start( struct Track_Filter* this );
58
59// Sets time that fade starts, and how long until track ends.
60void track_set_fade( struct Track_Filter* this, sample_count_t start, sample_count_t length );
61
62// Generates n samples into buf
63blargg_err_t track_play( struct Track_Filter* this, int n, sample_t buf [] );
64
65// Skips n samples
66blargg_err_t track_skip( struct Track_Filter* this, int n );
67
68// Number of samples played/skipped since start_track()
69static inline int track_sample_count( struct Track_Filter* this ) { return this->out_time; }
70
71// True if track ended. Causes are end of source samples, end of fade,
72// or excessive silence.
73static inline bool track_ended( struct Track_Filter* this ) { return this->track_ended_; }
74
75// Clears state
76void track_stop( struct Track_Filter* this );
77
78// For use by callbacks
79
80// Sets internal "track ended" flag and stops generation of further source samples
81static inline void track_set_end( struct Track_Filter* this ) { this->emu_track_ended_ = true; }
82
83// For use by skip_() callback
84blargg_err_t skippy_( struct Track_Filter* this, int count );
85void fill_buf( struct Track_Filter* this );
86
87// Skip and play callbacks
88blargg_err_t skip_( void* emu, int count );
89blargg_err_t play_( void* emu, int count, sample_t out [] );
90#endif
diff --git a/apps/codecs/libgme/vgm_emu.c b/apps/codecs/libgme/vgm_emu.c
index 391bd02d73..4f8a2adbc1 100644
--- a/apps/codecs/libgme/vgm_emu.c
+++ b/apps/codecs/libgme/vgm_emu.c
@@ -23,11 +23,6 @@ const char* const gme_wrong_file_type = "Wrong file type for this emulator";
23 23
24int const fm_gain = 3; // FM emulators are internally quieter to avoid 16-bit overflow 24int const fm_gain = 3; // FM emulators are internally quieter to avoid 16-bit overflow
25 25
26int const silence_max = 6; // seconds
27int const silence_threshold = 0x10;
28long const fade_block_size = 512;
29int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
30
31// VGM commands (Spec v1.50) 26// VGM commands (Spec v1.50)
32enum { 27enum {
33 cmd_gg_stereo = 0x4F, 28 cmd_gg_stereo = 0x4F,
@@ -53,15 +48,8 @@ enum {
53 48
54static void clear_track_vars( struct Vgm_Emu* this ) 49static void clear_track_vars( struct Vgm_Emu* this )
55{ 50{
56 this->out_time = 0; 51 this->current_track = -1;
57 this->emu_time = 0; 52 track_stop( &this->track_filter );
58 this->emu_track_ended_ = true;
59 this->track_ended = true;
60 this->fade_start = INT_MAX / 2 + 1;
61 this->fade_step = 1;
62 this->silence_time = 0;
63 this->silence_count = 0;
64 this->buf_remain = 0;
65} 53}
66 54
67int play_frame( struct Vgm_Emu* this, blip_time_t blip_time, int sample_count, sample_t* buf ); 55int play_frame( struct Vgm_Emu* this, blip_time_t blip_time, int sample_count, sample_t* buf );
@@ -77,9 +65,10 @@ void Vgm_init( struct Vgm_Emu* this )
77 this->tempo = (int)(FP_ONE_TEMPO); 65 this->tempo = (int)(FP_ONE_TEMPO);
78 66
79 // defaults 67 // defaults
80 this->max_initial_silence = 2; 68 this->tfilter = *track_get_setup( &this->track_filter );
81 this->silence_lookahead = 1; // tracks should already be trimmed 69 this->tfilter.max_initial = 2;
82 this->ignore_silence = false; 70 this->tfilter.lookahead = 1;
71 this->track_filter.silence_ignored_ = false;
83 72
84 // Disable oversampling by default 73 // Disable oversampling by default
85 this->disable_oversampling = true; 74 this->disable_oversampling = true;
@@ -88,10 +77,10 @@ void Vgm_init( struct Vgm_Emu* this )
88 Sms_apu_init( &this->psg ); 77 Sms_apu_init( &this->psg );
89 Synth_init( &this->pcm ); 78 Synth_init( &this->pcm );
90 79
91 Buffer_init( &this->buf ); 80 Buffer_init( &this->stereo_buf );
92 Blip_init( &this->blip_buf ); 81 Blip_init( &this->blip_buf );
93 82
94 // Init fm chips 83 // Init fm chips
95 Ym2413_init( &this->ym2413 ); 84 Ym2413_init( &this->ym2413 );
96 Ym2612_init( &this->ym2612 ); 85 Ym2612_init( &this->ym2612 );
97 86
@@ -105,7 +94,8 @@ void Vgm_init( struct Vgm_Emu* this )
105 94
106 // Unload 95 // Unload
107 this->voice_count = 0; 96 this->voice_count = 0;
108 clear_track_vars( this ); 97 this->voice_types = 0;
98 clear_track_vars( this );
109} 99}
110 100
111// Track info 101// Track info
@@ -150,13 +140,13 @@ static void parse_gd3( byte const* in, byte const* end, struct track_info_t* out
150 140
151int const gd3_header_size = 12; 141int const gd3_header_size = 12;
152 142
153static long check_gd3_header( byte const* h, long remain ) 143static int check_gd3_header( byte const* h, int remain )
154{ 144{
155 if ( remain < gd3_header_size ) return 0; 145 if ( remain < gd3_header_size ) return 0;
156 if ( memcmp( h, "Gd3 ", 4 ) ) return 0; 146 if ( memcmp( h, "Gd3 ", 4 ) ) return 0;
157 if ( get_le32( h + 4 ) >= 0x200 ) return 0; 147 if ( get_le32( h + 4 ) >= 0x200 ) return 0;
158 148
159 long gd3_size = get_le32( h + 8 ); 149 int gd3_size = get_le32( h + 8 );
160 if ( gd3_size > remain - gd3_header_size ) 150 if ( gd3_size > remain - gd3_header_size )
161 gd3_size = remain - gd3_header_size; 151 gd3_size = remain - gd3_header_size;
162 return gd3_size; 152 return gd3_size;
@@ -167,12 +157,12 @@ static byte const* gd3_data( struct Vgm_Emu* this, int* size )
167 if ( size ) 157 if ( size )
168 *size = 0; 158 *size = 0;
169 159
170 long gd3_offset = get_le32( header( this )->gd3_offset ) - 0x2C; 160 int gd3_offset = get_le32( header( this )->gd3_offset ) - 0x2C;
171 if ( gd3_offset < 0 ) 161 if ( gd3_offset < 0 )
172 return 0; 162 return 0;
173 163
174 byte const* gd3 = this->file_begin + header_size + gd3_offset; 164 byte const* gd3 = this->file_begin + header_size + gd3_offset;
175 long gd3_size = check_gd3_header( gd3, this->file_end - gd3 ); 165 int gd3_size = check_gd3_header( gd3, this->file_end - gd3 );
176 if ( !gd3_size ) 166 if ( !gd3_size )
177 return 0; 167 return 0;
178 168
@@ -184,10 +174,10 @@ static byte const* gd3_data( struct Vgm_Emu* this, int* size )
184 174
185static void get_vgm_length( struct header_t const* h, struct track_info_t* out ) 175static void get_vgm_length( struct header_t const* h, struct track_info_t* out )
186{ 176{
187 long length = get_le32( h->track_duration ) * 10 / 441; 177 int length = get_le32( h->track_duration ) * 10 / 441;
188 if ( length > 0 ) 178 if ( length > 0 )
189 { 179 {
190 long loop = get_le32( h->loop_duration ); 180 int loop = get_le32( h->loop_duration );
191 if ( loop > 0 && get_le32( h->loop_offset ) ) 181 if ( loop > 0 && get_le32( h->loop_offset ) )
192 { 182 {
193 out->loop_length = loop * 10 / 441; 183 out->loop_length = loop * 10 / 441;
@@ -285,24 +275,25 @@ blargg_err_t Vgm_load_mem( struct Vgm_Emu* this, byte const* new_data, long new_
285 Ym2612_enable( &this->ym2612, false ); 275 Ym2612_enable( &this->ym2612, false );
286 Ym2413_enable( &this->ym2413, false ); 276 Ym2413_enable( &this->ym2413, false );
287 277
288 Sound_set_tempo( this, (int)(FP_ONE_TEMPO) );
289
290 this->voice_count = sms_osc_count; 278 this->voice_count = sms_osc_count;
279 static int const types [8] = {
280 wave_type+1, wave_type+2, wave_type+3, noise_type+1,
281 0, 0, 0, 0
282 };
283 this->voice_types = types;
291 284
292 RETURN_ERR( setup_fm( this ) ); 285 RETURN_ERR( setup_fm( this ) );
293 286
294 // do after FM in case output buffer is changed 287 // do after FM in case output buffer is changed
295 // setup buffer 288 // setup buffer
296 this->clock_rate_ = this->psg_rate; 289 this->clock_rate_ = this->psg_rate;
297 Buffer_clock_rate( &this->buf, this->psg_rate ); 290 Buffer_clock_rate( &this->stereo_buf, this->psg_rate );
298 291 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
299 // Setup bass 292 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
300 this->buf_changed_count = Buffer_channels_changed_count( &this->buf );
301 293
302 // Post load 294 // Post load
303 Sound_set_tempo( this, this->tempo ); 295 Sound_set_tempo( this, this->tempo );
304 Sound_mute_voices( this, this->mute_mask_ ); 296 Sound_mute_voices( this, this->mute_mask_ );
305
306 return 0; 297 return 0;
307} 298}
308 299
@@ -362,42 +353,56 @@ blargg_err_t setup_fm( struct Vgm_Emu* this )
362// Emulation 353// Emulation
363 354
364blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time ); 355blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time );
365static blargg_err_t run_clocks( struct Vgm_Emu* this, blip_time_t* time_io, int msec ) 356static blip_time_t run_psg( struct Vgm_Emu* this, int msec )
366{ 357{
367 *time_io = run( this, msec * this->vgm_rate / 1000 ); 358 blip_time_t t = run( this, msec * this->vgm_rate / 1000 );
368 Sms_apu_end_frame( &this->psg, *time_io ); 359 Sms_apu_end_frame( &this->psg, t );
369 return 0; 360 return t;
370} 361}
371 362
363static void check_end( struct Vgm_Emu* this )
364{
365 if( this->pos >= this->file_end )
366 track_set_end( &this->track_filter );
367}
372 368
369static blargg_err_t run_clocks( struct Vgm_Emu* this, blip_time_t* time_io, int msec )
370{
371 check_end( this );
372 *time_io = run_psg( this, msec );
373 return 0;
374}
373 375
374static blargg_err_t play_( struct Vgm_Emu* this, long count, sample_t* out ) 376blargg_err_t play_( void *emu, int count, sample_t out [] )
375{ 377{
378 struct Vgm_Emu* this = (struct Vgm_Emu*) emu;
379
376 if ( !uses_fm( this ) ) { 380 if ( !uses_fm( this ) ) {
377 long remain = count; 381 int remain = count;
378 while ( remain ) 382 while ( remain )
379 { 383 {
380 remain -= Buffer_read_samples( &this->buf, &out [count - remain], remain ); 384 Buffer_disable_immediate_removal( &this->stereo_buf );
385 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
381 if ( remain ) 386 if ( remain )
382 { 387 {
383 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->buf ) ) 388 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
384 { 389 {
385 this->buf_changed_count = Buffer_channels_changed_count( &this->buf ); 390 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
386 391
387 // Remute voices 392 // Remute voices
388 Sound_mute_voices( this, this->mute_mask_ ); 393 Sound_mute_voices( this, this->mute_mask_ );
389 } 394 }
390 int msec = Buffer_length( &this->buf ); 395 int msec = Buffer_length( &this->stereo_buf );
391 blip_time_t clocks_emulated = (blargg_long) msec * this->clock_rate_ / 1000 - 100; 396 blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
392 RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) ); 397 RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) );
393 assert( clocks_emulated ); 398 assert( clocks_emulated );
394 Buffer_end_frame( &this->buf, clocks_emulated ); 399 Buffer_end_frame( &this->stereo_buf, clocks_emulated );
395 } 400 }
396 } 401 }
397 402
398 return 0; 403 return 0;
399 } 404 }
400 405
401 Resampler_play( &this->resampler, count, out, &this->blip_buf ); 406 Resampler_play( &this->resampler, count, out, &this->blip_buf );
402 return 0; 407 return 0;
403} 408}
@@ -414,7 +419,7 @@ static inline int command_len( int command )
414 check( len != 1 ); 419 check( len != 1 );
415 return len; 420 return len;
416} 421}
417 422
418static inline fm_time_t to_fm_time( struct Vgm_Emu* this, vgm_time_t t ) 423static inline fm_time_t to_fm_time( struct Vgm_Emu* this, vgm_time_t t )
419{ 424{
420 return (t * this->fm_time_factor + this->fm_time_offset) >> fm_time_bits; 425 return (t * this->fm_time_factor + this->fm_time_offset) >> fm_time_bits;
@@ -443,12 +448,10 @@ blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time )
443{ 448{
444 vgm_time_t vgm_time = this->vgm_time; 449 vgm_time_t vgm_time = this->vgm_time;
445 byte const* pos = this->pos; 450 byte const* pos = this->pos;
446 if ( pos >= this->file_end ) 451 /* if ( pos > this->file_end )
447 { 452 {
448 this->emu_track_ended_ = true; 453 warning( "Stream lacked end event" );
449 /* if ( pos > data_end ) 454 } */
450 warning( "Stream lacked end event" ); */
451 }
452 455
453 while ( vgm_time < end_time && pos < this->file_end ) 456 while ( vgm_time < end_time && pos < this->file_end )
454 { 457 {
@@ -517,7 +520,7 @@ blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time )
517 case cmd_data_block: { 520 case cmd_data_block: {
518 check( *pos == cmd_end ); 521 check( *pos == cmd_end );
519 int type = pos [1]; 522 int type = pos [1];
520 long size = get_le32( pos + 2 ); 523 int size = get_le32( pos + 2 );
521 pos += 6; 524 pos += 6;
522 if ( type == pcm_block_type ) 525 if ( type == pcm_block_type )
523 this->pcm_data = pos; 526 this->pcm_data = pos;
@@ -564,6 +567,8 @@ blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time )
564 567
565int play_frame( struct Vgm_Emu* this, blip_time_t blip_time, int sample_count, blip_sample_t out [] ) 568int play_frame( struct Vgm_Emu* this, blip_time_t blip_time, int sample_count, blip_sample_t out [] )
566{ 569{
570 check_end( this);
571
567 // to do: timing is working mostly by luck 572 // to do: timing is working mostly by luck
568 int min_pairs = (unsigned) sample_count / 2; 573 int min_pairs = (unsigned) sample_count / 2;
569 int vgm_time = (min_pairs << fm_time_bits) / this->fm_time_factor - 1; 574 int vgm_time = (min_pairs << fm_time_bits) / this->fm_time_factor - 1;
@@ -642,16 +647,18 @@ void update_fm_rates( struct Vgm_Emu* this, int* ym2413_rate, int* ym2612_rate )
642 647
643// Music Emu 648// Music Emu
644 649
645blargg_err_t Vgm_set_sample_rate( struct Vgm_Emu* this, long rate ) 650blargg_err_t Vgm_set_sample_rate( struct Vgm_Emu* this, int rate )
646{ 651{
647 require( !this->sample_rate ); // sample rate can't be changed once set 652 require( !this->sample_rate ); // sample rate can't be changed once set
648 RETURN_ERR( Blip_set_sample_rate( &this->blip_buf, rate, 1000 / 30 ) ); 653 RETURN_ERR( Blip_set_sample_rate( &this->blip_buf, rate, 1000 / 30 ) );
649 RETURN_ERR( Buffer_set_sample_rate( &this->buf, rate, 1000 / 20 ) ); 654 RETURN_ERR( Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 ) );
650 655
651 // Set bass frequency 656 // Set bass frequency
652 Buffer_bass_freq( &this->buf, 80 ); 657 Buffer_bass_freq( &this->stereo_buf, 80 );
653 658
654 this->sample_rate = rate; 659 this->sample_rate = rate;
660 RETURN_ERR( track_init( &this->track_filter, this ) );
661 this->tfilter.max_silence = 6 * stereo * this->sample_rate;
655 return 0; 662 return 0;
656} 663}
657 664
@@ -679,7 +686,7 @@ void Sound_mute_voices( struct Vgm_Emu* this, int mask )
679 } 686 }
680 else 687 else
681 { 688 {
682 struct channel_t ch = Buffer_channel( &this->buf ); 689 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
683 assert( (ch.center && ch.left && ch.right) || 690 assert( (ch.center && ch.left && ch.right) ||
684 (!ch.center && !ch.left && !ch.right) ); // all or nothing 691 (!ch.center && !ch.left && !ch.right) ); // all or nothing
685 set_voice( this, i, ch.center, ch.left, ch.right ); 692 set_voice( this, i, ch.center, ch.left, ch.right );
@@ -735,7 +742,6 @@ void Sound_set_tempo( struct Vgm_Emu* this, int t )
735 } 742 }
736} 743}
737 744
738void fill_buf( struct Vgm_Emu *this );
739blargg_err_t Vgm_start_track( struct Vgm_Emu* this ) 745blargg_err_t Vgm_start_track( struct Vgm_Emu* this )
740{ 746{
741 clear_track_vars( this ); 747 clear_track_vars( this );
@@ -750,7 +756,7 @@ blargg_err_t Vgm_start_track( struct Vgm_Emu* this )
750 this->vgm_time = 0; 756 this->vgm_time = 0;
751 if ( get_le32( header( this )->version ) >= 0x150 ) 757 if ( get_le32( header( this )->version ) >= 0x150 )
752 { 758 {
753 long data_offset = get_le32( header( this )->data_offset ); 759 int data_offset = get_le32( header( this )->data_offset );
754 check( data_offset ); 760 check( data_offset );
755 if ( data_offset ) 761 if ( data_offset )
756 this->pos += data_offset + offsetof (struct header_t,data_offset) - 0x40; 762 this->pos += data_offset + offsetof (struct header_t,data_offset) - 0x40;
@@ -764,266 +770,88 @@ blargg_err_t Vgm_start_track( struct Vgm_Emu* this )
764 if ( Ym2612_enabled( &this->ym2612 ) ) 770 if ( Ym2612_enabled( &this->ym2612 ) )
765 Ym2612_reset( &this->ym2612 ); 771 Ym2612_reset( &this->ym2612 );
766 772
767 Blip_clear( &this->blip_buf, 1 ); 773 Blip_clear( &this->blip_buf );
768 Resampler_clear( &this->resampler ); 774 Resampler_clear( &this->resampler );
769 } 775 }
770 776
771 this->fm_time_offset = 0; 777 this->fm_time_offset = 0;
772 778
773 Buffer_clear( &this->buf ); 779 Buffer_clear( &this->stereo_buf );
774 780
775 this->emu_track_ended_ = false; 781 // convert filter times to samples
776 this->track_ended = false; 782 struct setup_t s = this->tfilter;
783 s.max_initial *= this->sample_rate * stereo;
784 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
785 s.lookahead = 1;
786 #endif
787 track_setup( &this->track_filter, &s );
777 788
778 if ( !this->ignore_silence ) 789 return track_start( &this->track_filter );
779 {
780 // play until non-silence or end of track
781 long end;
782 for ( end = this->max_initial_silence * stereo * this->sample_rate; this->emu_time < end; )
783 {
784 fill_buf( this );
785 if ( this->buf_remain | (int) this->emu_track_ended_ )
786 break;
787 }
788
789 this->emu_time = this->buf_remain;
790 this->out_time = 0;
791 this->silence_time = 0;
792 this->silence_count = 0;
793 }
794 /* return track_ended() ? warning() : 0; */
795 return 0;
796} 790}
797 791
798// Tell/Seek 792// Tell/Seek
799 793
800static blargg_long msec_to_samples( blargg_long msec, long sample_rate ) 794static int msec_to_samples( int msec, int sample_rate )
801{ 795{
802 blargg_long sec = msec / 1000; 796 int sec = msec / 1000;
803 msec -= sec * 1000; 797 msec -= sec * 1000;
804 return (sec * sample_rate + msec * sample_rate / 1000) * stereo; 798 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
805} 799}
806 800
807long Track_tell( struct Vgm_Emu* this ) 801int Track_tell( struct Vgm_Emu* this )
808{ 802{
809 blargg_long rate = this->sample_rate * stereo; 803 int rate = this->sample_rate * stereo;
810 blargg_long sec = this->out_time / rate; 804 int sec = track_sample_count( &this->track_filter ) / rate;
811 return sec * 1000 + (this->out_time - sec * rate) * 1000 / rate; 805 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
812} 806}
813 807
814blargg_err_t Track_seek( struct Vgm_Emu* this, long msec ) 808blargg_err_t Track_seek( struct Vgm_Emu* this, int msec )
815{ 809{
816 blargg_long time = msec_to_samples( msec, this->sample_rate ); 810 int time = msec_to_samples( msec, this->sample_rate );
817 if ( time < this->out_time ) 811 if ( time < track_sample_count( &this->track_filter ) )
818 RETURN_ERR( Vgm_start_track( this ) ); 812 RETURN_ERR( Vgm_start_track( this ) );
819 return Track_skip( this, time - this->out_time ); 813 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
820} 814}
821 815
822blargg_err_t skip_( struct Vgm_Emu* this, long count ); 816blargg_err_t Track_skip( struct Vgm_Emu* this, int count )
823blargg_err_t Track_skip( struct Vgm_Emu* this, long count )
824{ 817{
825 this->out_time += count; 818 require( this->current_track >= 0 ); // start_track() must have been called already
826 819 return track_skip( &this->track_filter, count );
827 // remove from silence and buf first
828 {
829 long n = min( count, this->silence_count );
830 this->silence_count -= n;
831 count -= n;
832
833 n = min( count, this->buf_remain );
834 this->buf_remain -= n;
835 count -= n;
836 }
837
838 if ( count && !this->emu_track_ended_ )
839 {
840 this->emu_time += count;
841 if ( skip_( this, count ) )
842 this->emu_track_ended_ = true;
843 }
844
845 if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended
846 this->track_ended |= this->emu_track_ended_;
847
848 return 0;
849} 820}
850 821
851blargg_err_t skip_( struct Vgm_Emu* this, long count ) 822blargg_err_t skip_( void* emu, int count )
852{ 823{
824 struct Vgm_Emu* this = (struct Vgm_Emu*) emu;
825
853 // for long skip, mute sound 826 // for long skip, mute sound
854 const long threshold = 30000; 827 const int threshold = 32768;
855 if ( count > threshold ) 828 if ( count > threshold )
856 { 829 {
857 int saved_mute = this->mute_mask_; 830 int saved_mute = this->mute_mask_;
858 Sound_mute_voices( this, ~0 ); 831 Sound_mute_voices( this, ~0 );
859
860 while ( count > threshold / 2 && !this->emu_track_ended_ )
861 {
862 RETURN_ERR( play_( this, buf_size, this->buf_ ) );
863 count -= buf_size;
864 }
865
866 Sound_mute_voices( this, saved_mute );
867 }
868
869 while ( count && !this->emu_track_ended_ )
870 {
871 long n = buf_size;
872 if ( n > count )
873 n = count;
874 count -= n;
875 RETURN_ERR( play_( this, n, this->buf_ ) );
876 }
877 return 0;
878}
879 832
880// Fading 833 int n = count - threshold/2;
881 834 n &= ~(2048-1); // round to multiple of 2048
882void Track_set_fade( struct Vgm_Emu* this, long start_msec, long length_msec ) 835 count -= n;
883{ 836 RETURN_ERR( skippy_( &this->track_filter, n ) );
884 this->fade_step = this->sample_rate * length_msec / (fade_block_size * fade_shift * 1000 / stereo);
885 this->fade_start = msec_to_samples( start_msec, this->sample_rate );
886}
887
888// unit / pow( 2.0, (double) x / step )
889static int int_log( blargg_long x, int step, int unit )
890{
891 int shift = x / step;
892 int fraction = (x - shift * step) * unit / step;
893 return ((unit - fraction) + (fraction >> 1)) >> shift;
894}
895 837
896static void handle_fade( struct Vgm_Emu* this, long out_count, sample_t* out ) 838 Sound_mute_voices( this, saved_mute );
897{
898 int i;
899 for ( i = 0; i < out_count; i += fade_block_size )
900 {
901 int const shift = 14;
902 int const unit = 1 << shift;
903 int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size,
904 this->fade_step, unit );
905 if ( gain < (unit >> fade_shift) )
906 this->track_ended = this->emu_track_ended_ = true;
907
908 sample_t* io = &out [i];
909 int count;
910 for ( count = min( fade_block_size, out_count - i ); count; --count )
911 {
912 *io = (sample_t) ((*io * gain) >> shift);
913 ++io;
914 }
915 } 839 }
916}
917 840
918// Silence detection 841 return skippy_( &this->track_filter, count );
919
920static void emu_play( struct Vgm_Emu* this, long count, sample_t* out )
921{
922 this->emu_time += count;
923 if ( !this->emu_track_ended_ ) {
924 if ( play_( this, count, out ) )
925 this->emu_track_ended_ = true;
926 }
927 else
928 memset( out, 0, count * sizeof *out );
929} 842}
930 843
931// number of consecutive silent samples at end 844// Fading
932static long count_silence( sample_t* begin, long size )
933{
934 sample_t first = *begin;
935 *begin = silence_threshold; // sentinel
936 sample_t* p = begin + size;
937 while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
938 *begin = first;
939 return size - (p - begin);
940}
941 845
942// fill internal buffer and check it for silence 846void Track_set_fade( struct Vgm_Emu* this, int start_msec, int length_msec )
943void fill_buf( struct Vgm_Emu* this )
944{ 847{
945 assert( !this->buf_remain ); 848 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
946 if ( !this->emu_track_ended_ ) 849 length_msec * this->sample_rate / (1000 / stereo) );
947 {
948 emu_play( this, buf_size, this->buf_ );
949 long silence = count_silence( this->buf_, buf_size );
950 if ( silence < buf_size )
951 {
952 this->silence_time = this->emu_time - silence;
953 this->buf_remain = buf_size;
954 return;
955 }
956 }
957 this->silence_count += buf_size;
958} 850}
959 851
960blargg_err_t Vgm_play( struct Vgm_Emu* this, long out_count, sample_t* out ) 852blargg_err_t Vgm_play( struct Vgm_Emu* this, int out_count, sample_t* out )
961{ 853{
962 if ( this->track_ended ) 854 require( this->current_track >= 0 );
963 { 855 require( out_count % stereo == 0 );
964 memset( out, 0, out_count * sizeof *out ); 856 return track_play( &this->track_filter, out_count, out );
965 }
966 else
967 {
968 require( out_count % stereo == 0 );
969
970 assert( this->emu_time >= this->out_time );
971
972 // prints nifty graph of how far ahead we are when searching for silence
973 //debug_printf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" );
974
975 long pos = 0;
976 if ( this->silence_count )
977 {
978 // during a run of silence, run emulator at >=2x speed so it gets ahead
979 long ahead_time = this->silence_lookahead * (this->out_time + out_count - this->silence_time) + this->silence_time;
980 while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) )
981 fill_buf( this );
982
983 // fill with silence
984 pos = min( this->silence_count, out_count );
985 memset( out, 0, pos * sizeof *out );
986 this->silence_count -= pos;
987
988 if ( this->emu_time - this->silence_time > silence_max * stereo * this->sample_rate )
989 {
990 this->track_ended = this->emu_track_ended_ = true;
991 this->silence_count = 0;
992 this->buf_remain = 0;
993 }
994 }
995
996 if ( this->buf_remain )
997 {
998 // empty silence buf
999 long n = min( this->buf_remain, out_count - pos );
1000 memcpy( &out [pos], this->buf_ + (buf_size - this->buf_remain), n * sizeof *out );
1001 this->buf_remain -= n;
1002 pos += n;
1003 }
1004
1005 // generate remaining samples normally
1006 long remain = out_count - pos;
1007 if ( remain )
1008 {
1009 emu_play( this, remain, out + pos );
1010 this->track_ended |= this->emu_track_ended_;
1011
1012 if ( !this->ignore_silence || this->out_time > this->fade_start )
1013 {
1014 // check end for a new run of silence
1015 long silence = count_silence( out + pos, remain );
1016 if ( silence < remain )
1017 this->silence_time = this->emu_time - silence;
1018
1019 if ( this->emu_time - this->silence_time >= buf_size )
1020 fill_buf( this ); // cause silence detection on next play()
1021 }
1022 }
1023
1024 if ( this->out_time > this->fade_start )
1025 handle_fade( this, out_count, out );
1026 }
1027 this->out_time += out_count;
1028 return 0;
1029} 857}
diff --git a/apps/codecs/libgme/vgm_emu.h b/apps/codecs/libgme/vgm_emu.h
index 773b850a09..8c39482008 100644
--- a/apps/codecs/libgme/vgm_emu.h
+++ b/apps/codecs/libgme/vgm_emu.h
@@ -1,11 +1,13 @@
1// Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro VGM music file emulator 1// Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro VGM music file emulator
2 2
3// Game_Music_Emu 0.5.5 3// Game_Music_Emu 0.6-pre
4#ifndef VGM_EMU_H 4#ifndef VGM_EMU_H
5#define VGM_EMU_H 5#define VGM_EMU_H
6 6
7#include "blargg_common.h" 7#include "blargg_common.h"
8#include "blargg_source.h" 8#include "blargg_source.h"
9
10#include "track_filter.h"
9#include "resampler.h" 11#include "resampler.h"
10#include "multi_buffer.h" 12#include "multi_buffer.h"
11#include "ym2413_emu.h" 13#include "ym2413_emu.h"
@@ -17,7 +19,6 @@ typedef int fm_time_t;
17 19
18enum { fm_time_bits = 12 }; 20enum { fm_time_bits = 12 };
19enum { blip_time_bits = 12 }; 21enum { blip_time_bits = 12 };
20enum { buf_size = 2048 };
21 22
22// VGM header format 23// VGM header format
23enum { header_size = 0x40 }; 24enum { header_size = 0x40 };
@@ -46,9 +47,9 @@ enum { gme_max_field = 63 };
46struct track_info_t 47struct track_info_t
47{ 48{
48 /* times in milliseconds; -1 if unknown */ 49 /* times in milliseconds; -1 if unknown */
49 long length; 50 int length;
50 long intro_length; 51 int intro_length;
51 long loop_length; 52 int loop_length;
52 53
53 /* empty string if not available */ 54 /* empty string if not available */
54 char game [64]; 55 char game [64];
@@ -63,11 +64,11 @@ struct track_info_t
63// YM2413 sound chip emulator. I can provide one I've modified to work with the library. 64// YM2413 sound chip emulator. I can provide one I've modified to work with the library.
64struct Vgm_Emu { 65struct Vgm_Emu {
65 int fm_rate; 66 int fm_rate;
66 long psg_rate; 67 int psg_rate;
67 long vgm_rate; 68 int vgm_rate;
68 bool disable_oversampling; 69 bool disable_oversampling;
69 70
70 long fm_time_offset; 71 int fm_time_offset;
71 int fm_time_factor; 72 int fm_time_factor;
72 73
73 int blip_time_factor; 74 int blip_time_factor;
@@ -84,47 +85,34 @@ struct Vgm_Emu {
84 int dac_amp; 85 int dac_amp;
85 int dac_disabled; // -1 if disabled 86 int dac_disabled; // -1 if disabled
86 87
87 struct Blip_Buffer blip_buf;
88
89 // general 88 // general
90 long clock_rate_; 89 int current_track;
90 int clock_rate_;
91 unsigned buf_changed_count; 91 unsigned buf_changed_count;
92 int max_initial_silence; 92 int max_initial_silence;
93 int voice_count; 93 int voice_count;
94 int const *voice_types;
94 int mute_mask_; 95 int mute_mask_;
95 int tempo; 96 int tempo;
96 int gain; 97 int gain;
97 98
98 long sample_rate; 99 int sample_rate;
99
100 // track-specific
101 blargg_long out_time; // number of samples played since start of track
102 blargg_long emu_time; // number of samples emulator has generated since start of track
103 bool emu_track_ended_; // emulator has reached end of track
104 volatile bool track_ended;
105
106 // fading
107 blargg_long fade_start;
108 int fade_step;
109
110 // silence detection
111 int silence_lookahead; // speed to run emulator when looking ahead for silence
112 bool ignore_silence;
113 long silence_time; // number of samples where most recent silence began
114 long silence_count; // number of samples of silence to play before using buf
115 long buf_remain; // number of samples left in silence buffer
116 100
117 // larger items at the end 101 // larger items at the end
118 struct track_info_t info; 102 struct track_info_t info;
119 sample_t buf_ [buf_size]; 103
104 struct setup_t tfilter;
105 struct Track_Filter track_filter;
120 106
121 struct Ym2612_Emu ym2612; 107 struct Ym2612_Emu ym2612;
122 struct Ym2413_Emu ym2413; 108 struct Ym2413_Emu ym2413;
123 109
124 struct Sms_Apu psg; 110 struct Sms_Apu psg;
125 struct Blip_Synth pcm; 111 struct Blip_Synth pcm;
112 struct Blip_Buffer blip_buf;
113
126 struct Resampler resampler; 114 struct Resampler resampler;
127 struct Stereo_Buffer buf; 115 struct Multi_Buffer stereo_buf;
128}; 116};
129 117
130void Vgm_init( struct Vgm_Emu* this ); 118void Vgm_init( struct Vgm_Emu* this );
@@ -135,7 +123,7 @@ static inline void Vgm_disable_oversampling( struct Vgm_Emu* this, bool disable
135 123
136// Header for currently loaded file 124// Header for currently loaded file
137static inline struct header_t *header( struct Vgm_Emu* this ) { return (struct header_t*) this->file_begin; } 125static inline struct header_t *header( struct Vgm_Emu* this ) { return (struct header_t*) this->file_begin; }
138 126
139// Basic functionality (see Gme_File.h for file loading/track info functions) 127// Basic functionality (see Gme_File.h for file loading/track info functions)
140blargg_err_t Vgm_load_mem( struct Vgm_Emu* this, byte const* new_data, long new_size, bool parse_info ); 128blargg_err_t Vgm_load_mem( struct Vgm_Emu* this, byte const* new_data, long new_size, bool parse_info );
141 129
@@ -144,34 +132,46 @@ blargg_err_t Vgm_load_mem( struct Vgm_Emu* this, byte const* new_data, long new_
144static inline bool uses_fm( struct Vgm_Emu* this ) { return Ym2612_enabled( &this->ym2612 ) || Ym2413_enabled( &this->ym2413 ); } 132static inline bool uses_fm( struct Vgm_Emu* this ) { return Ym2612_enabled( &this->ym2612 ) || Ym2413_enabled( &this->ym2413 ); }
145 133
146// Set output sample rate. Must be called only once before loading file. 134// Set output sample rate. Must be called only once before loading file.
147blargg_err_t Vgm_set_sample_rate( struct Vgm_Emu* this, long sample_rate ); 135blargg_err_t Vgm_set_sample_rate( struct Vgm_Emu* this, int sample_rate );
148 136
149// Start a track, where 0 is the first track. Also clears warning string. 137// Start a track, where 0 is the first track. Also clears warning string.
150blargg_err_t Vgm_start_track( struct Vgm_Emu* this ); 138blargg_err_t Vgm_start_track( struct Vgm_Emu* this );
151 139
152// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation 140// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
153// errors set warning string, and major errors also end track. 141// errors set warning string, and major errors also end track.
154blargg_err_t Vgm_play( struct Vgm_Emu* this, long count, sample_t* buf ); 142blargg_err_t Vgm_play( struct Vgm_Emu* this, int count, sample_t* buf );
155 143
156// Track status/control 144// Track status/control
157 145
158// Number of milliseconds (1000 msec = 1 second) played since beginning of track 146// Number of milliseconds (1000 msec = 1 second) played since beginning of track
159long Track_tell( struct Vgm_Emu* this ); 147int Track_tell( struct Vgm_Emu* this );
160 148
161// Seek to new time in track. Seeking backwards or far forward can take a while. 149// Seek to new time in track. Seeking backwards or far forward can take a while.
162blargg_err_t Track_seek( struct Vgm_Emu* this, long msec ); 150blargg_err_t Track_seek( struct Vgm_Emu* this, int msec );
163 151
164// Skip n samples 152// Skip n samples
165blargg_err_t Track_skip( struct Vgm_Emu* this, long n ); 153blargg_err_t Track_skip( struct Vgm_Emu* this, int n );
166 154
167// Set start time and length of track fade out. Once fade ends track_ended() returns 155// Set start time and length of track fade out. Once fade ends track_ended() returns
168// true. Fade time can be changed while track is playing. 156// true. Fade time can be changed while track is playing.
169void Track_set_fade( struct Vgm_Emu* this, long start_msec, long length_msec ); 157void Track_set_fade( struct Vgm_Emu* this, int start_msec, int length_msec );
158
159// True if a track has reached its end
160static inline bool Track_ended( struct Vgm_Emu* this )
161{
162 return track_ended( &this->track_filter );
163}
164
165// Disables automatic end-of-track detection and skipping of silence at beginning
166static inline void Track_ignore_silence( struct Vgm_Emu* this, bool disable )
167{
168 this->track_filter.silence_ignored_ = disable;
169}
170 170
171// Get track length in milliseconds 171// Get track length in milliseconds
172static inline long Track_get_length( struct Vgm_Emu* this ) 172static inline int Track_get_length( struct Vgm_Emu* this )
173{ 173{
174 long length = this->info.length; 174 int length = this->info.length;
175 if ( length <= 0 ) 175 if ( length <= 0 )
176 { 176 {
177 length = this->info.intro_length + 2 * this->info.loop_length; // intro + 2 loops 177 length = this->info.intro_length + 2 * this->info.loop_length; // intro + 2 loops
@@ -181,20 +181,20 @@ static inline long Track_get_length( struct Vgm_Emu* this )
181 181
182 return length; 182 return length;
183} 183}
184 184
185// Sound customization 185// Sound customization
186 186
187// Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed. 187// Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
188// Track length as returned by track_info() assumes a tempo of 1.0. 188// Track length as returned by track_info() assumes a tempo of 1.0.
189void Sound_set_tempo( struct Vgm_Emu* this, int t ); 189void Sound_set_tempo( struct Vgm_Emu* this, int t );
190 190
191// Mute/unmute voice i, where voice 0 is first voice 191// Mute/unmute voice i, where voice 0 is first voice
192void Sound_mute_voice( struct Vgm_Emu* this, int index, bool mute ); 192void Sound_mute_voice( struct Vgm_Emu* this, int index, bool mute );
193 193
194// Set muting state of all voices at once using a bit mask, where -1 mutes them all, 194// Set muting state of all voices at once using a bit mask, where -1 mutes them all,
195// 0 unmutes them all, 0x01 mutes just the first voice, etc. 195// 0 unmutes them all, 0x01 mutes just the first voice, etc.
196void Sound_mute_voices( struct Vgm_Emu* this, int mask ); 196void Sound_mute_voices( struct Vgm_Emu* this, int mask );
197 197
198// Change overall output amplitude, where 1.0 results in minimal clamping. 198// Change overall output amplitude, where 1.0 results in minimal clamping.
199// Must be called before set_sample_rate(). 199// Must be called before set_sample_rate().
200static inline void Sound_set_gain( struct Vgm_Emu* this, int g ) 200static inline void Sound_set_gain( struct Vgm_Emu* this, int g )
@@ -203,5 +203,4 @@ static inline void Sound_set_gain( struct Vgm_Emu* this, int g )
203 this->gain = g; 203 this->gain = g;
204} 204}
205 205
206
207#endif 206#endif
diff --git a/apps/codecs/libgme/ym2612_emu.c b/apps/codecs/libgme/ym2612_emu.c
index a1f96e3d70..ee7947ef3b 100644
--- a/apps/codecs/libgme/ym2612_emu.c
+++ b/apps/codecs/libgme/ym2612_emu.c
@@ -4,7 +4,6 @@
4 4
5#include "ym2612_emu.h" 5#include "ym2612_emu.h"
6 6
7#include <assert.h>
8#include <stdlib.h> 7#include <stdlib.h>
9#include <string.h> 8#include <string.h>
10#include <limits.h> 9#include <limits.h>
diff --git a/apps/codecs/nsf.c b/apps/codecs/nsf.c
index 533972e110..7214b5d2a2 100644
--- a/apps/codecs/nsf.c
+++ b/apps/codecs/nsf.c
@@ -74,8 +74,8 @@ enum codec_status codec_run(void)
74 return CODEC_ERROR; 74 return CODEC_ERROR;
75 } 75 }
76 76
77 if ((err = Nsf_load(&nsf_emu, buf, ci->filesize))) { 77 if ((err = Nsf_load_mem(&nsf_emu, buf, ci->filesize))) {
78 DEBUGF("NSF: Nsf_load failed (%s)\n", err); 78 DEBUGF("NSF: Nsf_load_mem failed (%s)\n", err);
79 return CODEC_ERROR; 79 return CODEC_ERROR;
80 } 80 }
81 81
@@ -116,7 +116,7 @@ next_track:
116 116
117 /* Generate audio buffer */ 117 /* Generate audio buffer */
118 err = Nsf_play(&nsf_emu, CHUNK_SIZE, samples); 118 err = Nsf_play(&nsf_emu, CHUNK_SIZE, samples);
119 if (err || nsf_emu.track_ended) { 119 if (err || Track_ended(&nsf_emu)) {
120 track++; 120 track++;
121 if (track >= nsf_emu.track_count) break; 121 if (track >= nsf_emu.track_count) break;
122 goto next_track; 122 goto next_track;
diff --git a/apps/codecs/sgc.c b/apps/codecs/sgc.c
index 993c606c7e..348a54a2d3 100644
--- a/apps/codecs/sgc.c
+++ b/apps/codecs/sgc.c
@@ -83,7 +83,7 @@ enum codec_status codec_run(void)
83 } 83 }
84 84
85 if ((err = Sgc_load_mem(&sgc_emu, buf, ci->filesize))) { 85 if ((err = Sgc_load_mem(&sgc_emu, buf, ci->filesize))) {
86 DEBUGF("SGC: Sgc_load failed (%s)\n", err); 86 DEBUGF("SGC: Sgc_load_mem failed (%s)\n", err);
87 return CODEC_ERROR; 87 return CODEC_ERROR;
88 } 88 }
89 89
@@ -110,7 +110,7 @@ next_track:
110 110
111 /* Generate audio buffer */ 111 /* Generate audio buffer */
112 err = Sgc_play(&sgc_emu, CHUNK_SIZE, samples); 112 err = Sgc_play(&sgc_emu, CHUNK_SIZE, samples);
113 if (err || sgc_emu.track_ended) { 113 if (err || Track_ended(&sgc_emu)) {
114 track++; 114 track++;
115 if (track >= sgc_emu.track_count) break; 115 if (track >= sgc_emu.track_count) break;
116 goto next_track; 116 goto next_track;
diff --git a/apps/codecs/vgm.c b/apps/codecs/vgm.c
index 9e4f88779c..d7390291e1 100644
--- a/apps/codecs/vgm.c
+++ b/apps/codecs/vgm.c
@@ -130,7 +130,7 @@ enum codec_status codec_run(void)
130 130
131 /* Generate audio buffer */ 131 /* Generate audio buffer */
132 err = Vgm_play(&vgm_emu, CHUNK_SIZE, samples); 132 err = Vgm_play(&vgm_emu, CHUNK_SIZE, samples);
133 if (err || vgm_emu.track_ended) break; 133 if (err || Track_ended(&vgm_emu)) break;
134 134
135 ci->pcmbuf_insert(samples, NULL, CHUNK_SIZE >> 1); 135 ci->pcmbuf_insert(samples, NULL, CHUNK_SIZE >> 1);
136 136