summaryrefslogtreecommitdiff
path: root/apps/codecs/libgme/hes_emu.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libgme/hes_emu.c')
-rw-r--r--apps/codecs/libgme/hes_emu.c581
1 files changed, 174 insertions, 407 deletions
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}