summaryrefslogtreecommitdiff
path: root/apps/codecs/libgme/sgc_emu.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libgme/sgc_emu.c')
-rw-r--r--apps/codecs/libgme/sgc_emu.c960
1 files changed, 480 insertions, 480 deletions
diff --git a/apps/codecs/libgme/sgc_emu.c b/apps/codecs/libgme/sgc_emu.c
index e7253a8d5b..267f2c9271 100644
--- a/apps/codecs/libgme/sgc_emu.c
+++ b/apps/codecs/libgme/sgc_emu.c
@@ -1,480 +1,480 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/ 1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2 2
3#include "sgc_emu.h" 3#include "sgc_emu.h"
4 4
5/* Copyright (C) 2009 Shay Green. This module is free software; you 5/* Copyright (C) 2009 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser 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 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 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 9module 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 aint 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
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
22static void clear_track_vars( struct Sgc_Emu* this ) 22static void clear_track_vars( struct Sgc_Emu* this )
23{ 23{
24 this->current_track = -1; 24 this->current_track = -1;
25 track_stop( &this->track_filter ); 25 track_stop( &this->track_filter );
26} 26}
27 27
28void Sgc_init( struct Sgc_Emu* this ) 28void Sgc_init( struct Sgc_Emu* this )
29{ 29{
30 assert( offsetof (struct header_t,copyright [32]) == header_size ); 30 assert( offsetof (struct header_t,copyright [32]) == header_size );
31 31
32 this->sample_rate = 0; 32 this->sample_rate = 0;
33 this->mute_mask_ = 0; 33 this->mute_mask_ = 0;
34 this->tempo = (int)FP_ONE_TEMPO; 34 this->tempo = (int)FP_ONE_TEMPO;
35 this->gain = (int)FP_ONE_GAIN; 35 this->gain = (int)FP_ONE_GAIN;
36 36
37 // defaults 37 // defaults
38 this->tfilter = *track_get_setup( &this->track_filter ); 38 this->tfilter = *track_get_setup( &this->track_filter );
39 this->tfilter.max_initial = 2; 39 this->tfilter.max_initial = 2;
40 this->tfilter.lookahead = 6; 40 this->tfilter.lookahead = 6;
41 this->track_filter.silence_ignored_ = false; 41 this->track_filter.silence_ignored_ = false;
42 42
43 Sms_apu_init( &this->apu ); 43 Sms_apu_init( &this->apu );
44 Fm_apu_create( &this->fm_apu ); 44 Fm_apu_create( &this->fm_apu );
45 45
46 Rom_init( &this->rom, 0x4000 ); 46 Rom_init( &this->rom, 0x4000 );
47 Z80_init( &this->cpu ); 47 Z80_init( &this->cpu );
48 48
49 Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) ); 49 Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) );
50 50
51 // Unload 51 // Unload
52 this->voice_count = 0; 52 this->voice_count = 0;
53 this->voice_types = 0; 53 this->voice_types = 0;
54 clear_track_vars( this ); 54 clear_track_vars( this );
55} 55}
56 56
57// Setup 57// Setup
58 58
59blargg_err_t Sgc_load_mem( struct Sgc_Emu* this, const void* data, long size ) 59blargg_err_t Sgc_load_mem( struct Sgc_Emu* this, const void* data, long size )
60{ 60{
61 RETURN_ERR( Rom_load( &this->rom, data, size, header_size, &this->header, 0 ) ); 61 RETURN_ERR( Rom_load( &this->rom, data, size, header_size, &this->header, 0 ) );
62 62
63 if ( !valid_tag( &this->header ) ) 63 if ( !valid_tag( &this->header ) )
64 return gme_wrong_file_type; 64 return gme_wrong_file_type;
65 65
66 /* if ( header.vers != 1 ) 66 /* if ( header.vers != 1 )
67 warning( "Unknown file version" ); */ 67 warning( "Unknown file version" ); */
68 68
69 /* if ( header.system > 2 ) 69 /* if ( header.system > 2 )
70 warning( "Unknown system" ); */ 70 warning( "Unknown system" ); */
71 71
72 addr_t load_addr = get_le16( this->header.load_addr ); 72 addr_t load_addr = get_le16( this->header.load_addr );
73 /* if ( load_addr < 0x400 ) 73 /* if ( load_addr < 0x400 )
74 set_warning( "Invalid load address" ); */ 74 set_warning( "Invalid load address" ); */
75 75
76 Rom_set_addr( &this->rom, load_addr ); 76 Rom_set_addr( &this->rom, load_addr );
77 this->play_period = clock_rate( this ) / 60; 77 this->play_period = clock_rate( this ) / 60;
78 78
79 if ( sega_mapping( this ) && Fm_apu_supported() ) 79 if ( sega_mapping( this ) && Fm_apu_supported() )
80 RETURN_ERR( Fm_apu_init( &this->fm_apu, clock_rate( this ), clock_rate( this ) / 72 ) ); 80 RETURN_ERR( Fm_apu_init( &this->fm_apu, clock_rate( this ), clock_rate( this ) / 72 ) );
81 81
82 this->m3u.size = 0; 82 this->m3u.size = 0;
83 this->track_count = this->header.song_count; 83 this->track_count = this->header.song_count;
84 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 [sms_osc_count + fm_apu_osc_count] = { 85 static int const types [sms_osc_count + fm_apu_osc_count] = {
86 wave_type+1, wave_type+2, wave_type+3, mixed_type+1, mixed_type+2 86 wave_type+1, wave_type+2, wave_type+3, mixed_type+1, mixed_type+2
87 }; 87 };
88 this->voice_types = types; 88 this->voice_types = types;
89 89
90 Sms_apu_volume( &this->apu, this->gain ); 90 Sms_apu_volume( &this->apu, this->gain );
91 Fm_apu_volume( &this->fm_apu, this->gain ); 91 Fm_apu_volume( &this->fm_apu, this->gain );
92 92
93 // Setup buffer 93 // Setup buffer
94 this->clock_rate_ = clock_rate( this ); 94 this->clock_rate_ = clock_rate( this );
95 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 ) ); 96 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
97 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); 97 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
98 98
99 Sound_set_tempo( this, this->tempo ); 99 Sound_set_tempo( this, this->tempo );
100 Sound_mute_voices( this, this->mute_mask_ ); 100 Sound_mute_voices( this, this->mute_mask_ );
101 return 0; 101 return 0;
102} 102}
103 103
104static void Sound_set_voice( struct Sgc_Emu* this, int i, struct Blip_Buffer* c, struct Blip_Buffer* l, struct Blip_Buffer* r ) 104static void Sound_set_voice( struct Sgc_Emu* this, int i, struct Blip_Buffer* c, struct Blip_Buffer* l, struct Blip_Buffer* r )
105{ 105{
106 if ( i < sms_osc_count ) 106 if ( i < sms_osc_count )
107 Sms_apu_set_output( &this->apu, i, c, l, r ); 107 Sms_apu_set_output( &this->apu, i, c, l, r );
108 else 108 else
109 Fm_apu_set_output( &this->fm_apu, c ); 109 Fm_apu_set_output( &this->fm_apu, c );
110} 110}
111 111
112static blargg_err_t run_clocks( struct Sgc_Emu* this, blip_time_t* duration, int msec ) 112static blargg_err_t run_clocks( struct Sgc_Emu* this, blip_time_t* duration, int msec )
113{ 113{
114#if defined(ROCKBOX) 114#if defined(ROCKBOX)
115 (void) msec; 115 (void) msec;
116#endif 116#endif
117 117
118 cpu_time_t t = *duration; 118 cpu_time_t t = *duration;
119 while ( Z80_time( &this->cpu ) < t ) 119 while ( Z80_time( &this->cpu ) < t )
120 { 120 {
121 cpu_time_t next = min( t, this->next_play ); 121 cpu_time_t next = min( t, this->next_play );
122 if ( run_cpu( this, next ) ) 122 if ( run_cpu( this, next ) )
123 { 123 {
124 /* warning( "Unsupported CPU instruction" ); */ 124 /* warning( "Unsupported CPU instruction" ); */
125 Z80_set_time( &this->cpu, next ); 125 Z80_set_time( &this->cpu, next );
126 } 126 }
127 127
128 if ( this->cpu.r.pc == this->idle_addr ) 128 if ( this->cpu.r.pc == this->idle_addr )
129 Z80_set_time( &this->cpu, next ); 129 Z80_set_time( &this->cpu, next );
130 130
131 if ( Z80_time( &this->cpu ) >= this->next_play ) 131 if ( Z80_time( &this->cpu ) >= this->next_play )
132 { 132 {
133 this->next_play += this->play_period; 133 this->next_play += this->play_period;
134 if ( this->cpu.r.pc == this->idle_addr ) 134 if ( this->cpu.r.pc == this->idle_addr )
135 jsr( this, this->header.play_addr ); 135 jsr( this, this->header.play_addr );
136 } 136 }
137 } 137 }
138 138
139 this->next_play -= t; 139 this->next_play -= t;
140 check( this->next_play >= 0 ); 140 check( this->next_play >= 0 );
141 Z80_adjust_time( &this->cpu, -t ); 141 Z80_adjust_time( &this->cpu, -t );
142 142
143 Sms_apu_end_frame( &this->apu, t ); 143 Sms_apu_end_frame( &this->apu, t );
144 if ( sega_mapping( this ) && this->fm_accessed ) 144 if ( sega_mapping( this ) && this->fm_accessed )
145 { 145 {
146 if ( Fm_apu_supported() ) 146 if ( Fm_apu_supported() )
147 Fm_apu_end_frame( &this->fm_apu, t ); 147 Fm_apu_end_frame( &this->fm_apu, t );
148 /* else 148 /* else
149 warning( "FM sound not supported" ); */ 149 warning( "FM sound not supported" ); */
150 } 150 }
151 151
152 return 0; 152 return 0;
153} 153}
154 154
155// Emulation 155// Emulation
156 156
157void cpu_out( struct Sgc_Emu* this, cpu_time_t time, addr_t addr, int data ) 157void cpu_out( struct Sgc_Emu* this, cpu_time_t time, addr_t addr, int data )
158{ 158{
159 int port = addr & 0xFF; 159 int port = addr & 0xFF;
160 160
161 if ( sega_mapping( this ) ) 161 if ( sega_mapping( this ) )
162 { 162 {
163 switch ( port ) 163 switch ( port )
164 { 164 {
165 case 0x06: 165 case 0x06:
166 Sms_apu_write_ggstereo( &this->apu, time, data ); 166 Sms_apu_write_ggstereo( &this->apu, time, data );
167 return; 167 return;
168 168
169 case 0x7E: 169 case 0x7E:
170 case 0x7F: 170 case 0x7F:
171 Sms_apu_write_data( &this->apu, time, data ); /* dprintf( "$7E<-%02X\n", data ); */ 171 Sms_apu_write_data( &this->apu, time, data ); /* dprintf( "$7E<-%02X\n", data ); */
172 return; 172 return;
173 173
174 case 0xF0: 174 case 0xF0:
175 this->fm_accessed = true; 175 this->fm_accessed = true;
176 if ( Fm_apu_supported() ) 176 if ( Fm_apu_supported() )
177 Fm_apu_write_addr( &this->fm_apu, data );//, dprintf( "$F0<-%02X\n", data ); 177 Fm_apu_write_addr( &this->fm_apu, data );//, dprintf( "$F0<-%02X\n", data );
178 return; 178 return;
179 179
180 case 0xF1: 180 case 0xF1:
181 this->fm_accessed = true; 181 this->fm_accessed = true;
182 if ( Fm_apu_supported() ) 182 if ( Fm_apu_supported() )
183 Fm_apu_write_data( &this->fm_apu, time, data );//, dprintf( "$F1<-%02X\n", data ); 183 Fm_apu_write_data( &this->fm_apu, time, data );//, dprintf( "$F1<-%02X\n", data );
184 return; 184 return;
185 } 185 }
186 } 186 }
187 else if ( port >= 0xE0 ) 187 else if ( port >= 0xE0 )
188 { 188 {
189 Sms_apu_write_data( &this->apu, time, data ); 189 Sms_apu_write_data( &this->apu, time, data );
190 return; 190 return;
191 } 191 }
192} 192}
193 193
194void jsr( struct Sgc_Emu* this, byte addr [2] ) 194void jsr( struct Sgc_Emu* this, byte addr [2] )
195{ 195{
196 *Z80_write( &this->cpu, --this->cpu.r.sp ) = this->idle_addr >> 8; 196 *Z80_write( &this->cpu, --this->cpu.r.sp ) = this->idle_addr >> 8;
197 *Z80_write( &this->cpu, --this->cpu.r.sp ) = this->idle_addr & 0xFF; 197 *Z80_write( &this->cpu, --this->cpu.r.sp ) = this->idle_addr & 0xFF;
198 this->cpu.r.pc = get_le16( addr ); 198 this->cpu.r.pc = get_le16( addr );
199} 199}
200 200
201static void set_bank( struct Sgc_Emu* this, int bank, void const* data ) 201static void set_bank( struct Sgc_Emu* this, int bank, void const* data )
202{ 202{
203 //dprintf( "map bank %d to %p\n", bank, (byte*) data - rom.at_addr( 0 ) ); 203 //dprintf( "map bank %d to %p\n", bank, (byte*) data - rom.at_addr( 0 ) );
204 Z80_map_mem( &this->cpu, bank * this->rom.bank_size, this->rom.bank_size, this->unmapped_write, data ); 204 Z80_map_mem( &this->cpu, bank * this->rom.bank_size, this->rom.bank_size, this->unmapped_write, data );
205} 205}
206 206
207void cpu_write( struct Sgc_Emu* this, addr_t addr, int data ) 207void cpu_write( struct Sgc_Emu* this, addr_t addr, int data )
208{ 208{
209 if ( (addr ^ 0xFFFC) > 3 || !sega_mapping( this ) ) 209 if ( (addr ^ 0xFFFC) > 3 || !sega_mapping( this ) )
210 { 210 {
211 *Z80_write( &this->cpu, addr ) = data; 211 *Z80_write( &this->cpu, addr ) = data;
212 return; 212 return;
213 } 213 }
214 214
215 switch ( addr ) 215 switch ( addr )
216 { 216 {
217 case 0xFFFC: 217 case 0xFFFC:
218 Z80_map_mem_rw( &this->cpu, 2 * this->rom.bank_size, this->rom.bank_size, this->ram2 ); 218 Z80_map_mem_rw( &this->cpu, 2 * this->rom.bank_size, this->rom.bank_size, this->ram2 );
219 if ( data & 0x08 ) 219 if ( data & 0x08 )
220 break; 220 break;
221 221
222 this->bank2 = this->ram2; 222 this->bank2 = this->ram2;
223 // FALL THROUGH 223 // FALL THROUGH
224 224
225 case 0xFFFF: { 225 case 0xFFFF: {
226 bool rom_mapped = (Z80_read( &this->cpu, 2 * this->rom.bank_size ) == this->bank2); 226 bool rom_mapped = (Z80_read( &this->cpu, 2 * this->rom.bank_size ) == this->bank2);
227 this->bank2 = Rom_at_addr( &this->rom, data * this->rom.bank_size ); 227 this->bank2 = Rom_at_addr( &this->rom, data * this->rom.bank_size );
228 if ( rom_mapped ) 228 if ( rom_mapped )
229 set_bank( this, 2, this->bank2 ); 229 set_bank( this, 2, this->bank2 );
230 break; 230 break;
231 } 231 }
232 232
233 case 0xFFFD: 233 case 0xFFFD:
234 set_bank( this, 0, Rom_at_addr( &this->rom, data * this->rom.bank_size ) ); 234 set_bank( this, 0, Rom_at_addr( &this->rom, data * this->rom.bank_size ) );
235 break; 235 break;
236 236
237 case 0xFFFE: 237 case 0xFFFE:
238 set_bank( this, 1, Rom_at_addr( &this->rom, data * this->rom.bank_size ) ); 238 set_bank( this, 1, Rom_at_addr( &this->rom, data * this->rom.bank_size ) );
239 break; 239 break;
240 } 240 }
241} 241}
242 242
243blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, int rate ) 243blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, int rate )
244{ 244{
245 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
246 Buffer_init( &this->stereo_buf ); 246 Buffer_init( &this->stereo_buf );
247 Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 ); 247 Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 );
248 248
249 // Set buffer bass 249 // Set buffer bass
250 Buffer_bass_freq( &this->stereo_buf, 80 ); 250 Buffer_bass_freq( &this->stereo_buf, 80 );
251 251
252 this->sample_rate = rate; 252 this->sample_rate = rate;
253 RETURN_ERR( track_init( &this->track_filter, this ) ); 253 RETURN_ERR( track_init( &this->track_filter, this ) );
254 this->tfilter.max_silence = 6 * stereo * this->sample_rate; 254 this->tfilter.max_silence = 6 * stereo * this->sample_rate;
255 return 0; 255 return 0;
256} 256}
257 257
258void Sound_mute_voice( struct Sgc_Emu* this, int index, bool mute ) 258void Sound_mute_voice( struct Sgc_Emu* this, int index, bool mute )
259{ 259{
260 require( (unsigned) index < (unsigned) this->voice_count ); 260 require( (unsigned) index < (unsigned) this->voice_count );
261 int bit = 1 << index; 261 int bit = 1 << index;
262 int mask = this->mute_mask_ | bit; 262 int mask = this->mute_mask_ | bit;
263 if ( !mute ) 263 if ( !mute )
264 mask ^= bit; 264 mask ^= bit;
265 Sound_mute_voices( this, mask ); 265 Sound_mute_voices( this, mask );
266} 266}
267 267
268void Sound_mute_voices( struct Sgc_Emu* this, int mask ) 268void Sound_mute_voices( struct Sgc_Emu* this, int mask )
269{ 269{
270 require( this->sample_rate ); // sample rate must be set first 270 require( this->sample_rate ); // sample rate must be set first
271 this->mute_mask_ = mask; 271 this->mute_mask_ = mask;
272 272
273 int i; 273 int i;
274 for ( i = this->voice_count; i--; ) 274 for ( i = this->voice_count; i--; )
275 { 275 {
276 if ( mask & (1 << i) ) 276 if ( mask & (1 << i) )
277 { 277 {
278 Sound_set_voice( this, i, 0, 0, 0 ); 278 Sound_set_voice( this, i, 0, 0, 0 );
279 } 279 }
280 else 280 else
281 { 281 {
282 struct channel_t ch = Buffer_channel( &this->stereo_buf, i ); 282 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
283 assert( (ch.center && ch.left && ch.right) || 283 assert( (ch.center && ch.left && ch.right) ||
284 (!ch.center && !ch.left && !ch.right) ); // all or nothing 284 (!ch.center && !ch.left && !ch.right) ); // all or nothing
285 Sound_set_voice( this, i, ch.center, ch.left, ch.right ); 285 Sound_set_voice( this, i, ch.center, ch.left, ch.right );
286 } 286 }
287 } 287 }
288} 288}
289 289
290void Sound_set_tempo( struct Sgc_Emu* this, int t ) 290void Sound_set_tempo( struct Sgc_Emu* this, int t )
291{ 291{
292 require( this->sample_rate ); // sample rate must be set first 292 require( this->sample_rate ); // sample rate must be set first
293 int const min = (int)(FP_ONE_TEMPO*0.02); 293 int const min = (int)(FP_ONE_TEMPO*0.02);
294 int const max = (int)(FP_ONE_TEMPO*4.00); 294 int const max = (int)(FP_ONE_TEMPO*4.00);
295 if ( t < min ) t = min; 295 if ( t < min ) t = min;
296 if ( t > max ) t = max; 296 if ( t > max ) t = max;
297 this->tempo = t; 297 this->tempo = t;
298 298
299 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);
300} 300}
301 301
302blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track ) 302blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track )
303{ 303{
304 clear_track_vars( this ); 304 clear_track_vars( this );
305 305
306 // Remap track if playlist available 306 // Remap track if playlist available
307 if ( this->m3u.size > 0 ) { 307 if ( this->m3u.size > 0 ) {
308 struct entry_t* e = &this->m3u.entries[track]; 308 struct entry_t* e = &this->m3u.entries[track];
309 track = e->track; 309 track = e->track;
310 } 310 }
311 311
312 this->current_track = track; 312 this->current_track = track;
313 313
314 if ( sega_mapping( this ) ) 314 if ( sega_mapping( this ) )
315 { 315 {
316 Sms_apu_reset( &this->apu, 0, 0 ); 316 Sms_apu_reset( &this->apu, 0, 0 );
317 Fm_apu_reset( &this->fm_apu ); 317 Fm_apu_reset( &this->fm_apu );
318 this->fm_accessed = false; 318 this->fm_accessed = false;
319 } 319 }
320 else 320 else
321 { 321 {
322 Sms_apu_reset( &this->apu, 0x0003, 15 ); 322 Sms_apu_reset( &this->apu, 0x0003, 15 );
323 } 323 }
324 324
325 memset( this->ram , 0, sizeof this->ram ); 325 memset( this->ram , 0, sizeof this->ram );
326 memset( this->ram2, 0, sizeof this->ram2 ); 326 memset( this->ram2, 0, sizeof this->ram2 );
327 memset( this->vectors, 0xFF, sizeof this->vectors ); 327 memset( this->vectors, 0xFF, sizeof this->vectors );
328 Z80_reset( &this->cpu, this->unmapped_write, this->rom.unmapped ); 328 Z80_reset( &this->cpu, this->unmapped_write, this->rom.unmapped );
329 329
330 if ( sega_mapping( this ) ) 330 if ( sega_mapping( this ) )
331 { 331 {
332 this->vectors_addr = 0x10000 - page_size; 332 this->vectors_addr = 0x10000 - page_size;
333 this->idle_addr = this->vectors_addr; 333 this->idle_addr = this->vectors_addr;
334 int i; 334 int i;
335 for ( i = 1; i < 8; ++i ) 335 for ( i = 1; i < 8; ++i )
336 { 336 {
337 this->vectors [i*8 + 0] = 0xC3; // JP addr 337 this->vectors [i*8 + 0] = 0xC3; // JP addr
338 this->vectors [i*8 + 1] = this->header.rst_addrs [i - 1] & 0xff; 338 this->vectors [i*8 + 1] = this->header.rst_addrs [i - 1] & 0xff;
339 this->vectors [i*8 + 2] = this->header.rst_addrs [i - 1] >> 8; 339 this->vectors [i*8 + 2] = this->header.rst_addrs [i - 1] >> 8;
340 } 340 }
341 341
342 Z80_map_mem_rw( &this->cpu, 0xC000, 0x2000, this->ram ); 342 Z80_map_mem_rw( &this->cpu, 0xC000, 0x2000, this->ram );
343 Z80_map_mem( &this->cpu, this->vectors_addr, page_size, this->unmapped_write, this->vectors ); 343 Z80_map_mem( &this->cpu, this->vectors_addr, page_size, this->unmapped_write, this->vectors );
344 344
345 this->bank2 = NULL; 345 this->bank2 = NULL;
346 for ( i = 0; i < 4; ++i ) 346 for ( i = 0; i < 4; ++i )
347 cpu_write( this, 0xFFFC + i, this->header.mapping [i] ); 347 cpu_write( this, 0xFFFC + i, this->header.mapping [i] );
348 } 348 }
349 else 349 else
350 { 350 {
351 if ( !this->coleco_bios ) 351 if ( !this->coleco_bios )
352 return "Coleco BIOS not set"; /* BLARGG_ERR( BLARGG_ERR_CALLER, "Coleco BIOS not set" ); */ 352 return "Coleco BIOS not set"; /* BLARGG_ERR( BLARGG_ERR_CALLER, "Coleco BIOS not set" ); */
353 353
354 this->vectors_addr = 0; 354 this->vectors_addr = 0;
355 Z80_map_mem( &this->cpu, 0, 0x2000, this->unmapped_write, this->coleco_bios ); 355 Z80_map_mem( &this->cpu, 0, 0x2000, this->unmapped_write, this->coleco_bios );
356 int i; 356 int i;
357 for ( i = 0; i < 8; ++i ) 357 for ( i = 0; i < 8; ++i )
358 Z80_map_mem_rw( &this->cpu, 0x6000 + i*0x400, 0x400, this->ram ); 358 Z80_map_mem_rw( &this->cpu, 0x6000 + i*0x400, 0x400, this->ram );
359 359
360 this->idle_addr = 0x2000; 360 this->idle_addr = 0x2000;
361 Z80_map_mem( &this->cpu, 0x2000, page_size, this->unmapped_write, this->vectors ); 361 Z80_map_mem( &this->cpu, 0x2000, page_size, this->unmapped_write, this->vectors );
362 362
363 for ( i = 0; i < 0x8000 / this->rom.bank_size; ++i ) 363 for ( i = 0; i < 0x8000 / this->rom.bank_size; ++i )
364 { 364 {
365 int addr = 0x8000 + i*this->rom.bank_size; 365 int addr = 0x8000 + i*this->rom.bank_size;
366 Z80_map_mem( &this->cpu, addr, this->rom.bank_size, this->unmapped_write, Rom_at_addr( &this->rom, addr ) ); 366 Z80_map_mem( &this->cpu, addr, this->rom.bank_size, this->unmapped_write, Rom_at_addr( &this->rom, addr ) );
367 } 367 }
368 } 368 }
369 369
370 this->cpu.r.sp = get_le16( this->header.stack_ptr ); 370 this->cpu.r.sp = get_le16( this->header.stack_ptr );
371 this->cpu.r.b.a = track; 371 this->cpu.r.b.a = track;
372 this->next_play = this->play_period; 372 this->next_play = this->play_period;
373 373
374 jsr( this, this->header.init_addr ); 374 jsr( this, this->header.init_addr );
375 375
376 Buffer_clear( &this->stereo_buf ); 376 Buffer_clear( &this->stereo_buf );
377 377
378 // convert filter times to samples 378 // convert filter times to samples
379 struct setup_t s = this->tfilter; 379 struct setup_t s = this->tfilter;
380 s.max_initial *= this->sample_rate * stereo; 380 s.max_initial *= this->sample_rate * stereo;
381 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD 381 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
382 s.lookahead = 1; 382 s.lookahead = 1;
383 #endif 383 #endif
384 track_setup( &this->track_filter, &s ); 384 track_setup( &this->track_filter, &s );
385 385
386 return track_start( &this->track_filter ); 386 return track_start( &this->track_filter );
387} 387}
388 388
389// Tell/Seek 389// Tell/Seek
390 390
391static int msec_to_samples( int msec, int sample_rate ) 391static int msec_to_samples( int msec, int sample_rate )
392{ 392{
393 int sec = msec / 1000; 393 int sec = msec / 1000;
394 msec -= sec * 1000; 394 msec -= sec * 1000;
395 return (sec * sample_rate + msec * sample_rate / 1000) * stereo; 395 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
396} 396}
397 397
398int Track_tell( struct Sgc_Emu* this ) 398int Track_tell( struct Sgc_Emu* this )
399{ 399{
400 int rate = this->sample_rate * stereo; 400 int rate = this->sample_rate * stereo;
401 int sec = track_sample_count( &this->track_filter ) / rate; 401 int sec = track_sample_count( &this->track_filter ) / rate;
402 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate; 402 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
403} 403}
404 404
405blargg_err_t Track_seek( struct Sgc_Emu* this, int msec ) 405blargg_err_t Track_seek( struct Sgc_Emu* this, int msec )
406{ 406{
407 int time = msec_to_samples( msec, this->sample_rate ); 407 int time = msec_to_samples( msec, this->sample_rate );
408 if ( time < track_sample_count( &this->track_filter ) ) 408 if ( time < track_sample_count( &this->track_filter ) )
409 RETURN_ERR( Sgc_start_track( this, this->current_track ) ); 409 RETURN_ERR( Sgc_start_track( this, this->current_track ) );
410 return Track_skip( this, time - track_sample_count( &this->track_filter ) ); 410 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
411} 411}
412 412
413blargg_err_t Track_skip( struct Sgc_Emu* this, int count ) 413blargg_err_t Track_skip( struct Sgc_Emu* this, int count )
414{ 414{
415 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
416 return track_skip( &this->track_filter, count ); 416 return track_skip( &this->track_filter, count );
417} 417}
418 418
419blargg_err_t skip_( void* emu, int count ) 419blargg_err_t skip_( void* emu, int count )
420{ 420{
421 struct Sgc_Emu* this = (struct Sgc_Emu*) emu; 421 struct Sgc_Emu* this = (struct Sgc_Emu*) emu;
422 422
423 // for long skip, mute sound 423 // for long skip, mute sound
424 const int threshold = 32768; 424 const int threshold = 32768;
425 if ( count > threshold ) 425 if ( count > threshold )
426 { 426 {
427 int saved_mute = this->mute_mask_; 427 int saved_mute = this->mute_mask_;
428 Sound_mute_voices( this, ~0 ); 428 Sound_mute_voices( this, ~0 );
429 429
430 int n = count - threshold/2; 430 int n = count - threshold/2;
431 n &= ~(2048-1); // round to multiple of 2048 431 n &= ~(2048-1); // round to multiple of 2048
432 count -= n; 432 count -= n;
433 RETURN_ERR( skippy_( &this->track_filter, n ) ); 433 RETURN_ERR( skippy_( &this->track_filter, n ) );
434 434
435 Sound_mute_voices( this, saved_mute ); 435 Sound_mute_voices( this, saved_mute );
436 } 436 }
437 437
438 return skippy_( &this->track_filter, count ); 438 return skippy_( &this->track_filter, count );
439} 439}
440 440
441void Track_set_fade( struct Sgc_Emu* this, int start_msec, int length_msec ) 441void Track_set_fade( struct Sgc_Emu* this, int start_msec, int length_msec )
442{ 442{
443 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ), 443 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
444 length_msec * this->sample_rate / (1000 / stereo) ); 444 length_msec * this->sample_rate / (1000 / stereo) );
445} 445}
446 446
447blargg_err_t Sgc_play( struct Sgc_Emu* this, int out_count, sample_t* out ) 447blargg_err_t Sgc_play( struct Sgc_Emu* this, int out_count, sample_t* out )
448{ 448{
449 require( this->current_track >= 0 ); 449 require( this->current_track >= 0 );
450 require( out_count % stereo == 0 ); 450 require( out_count % stereo == 0 );
451 return track_play( &this->track_filter, out_count, out ); 451 return track_play( &this->track_filter, out_count, out );
452} 452}
453 453
454blargg_err_t play_( void* emu, int count, sample_t out [] ) 454blargg_err_t play_( void* emu, int count, sample_t out [] )
455{ 455{
456 struct Sgc_Emu* this = (struct Sgc_Emu*) emu; 456 struct Sgc_Emu* this = (struct Sgc_Emu*) emu;
457 457
458 int remain = count; 458 int remain = count;
459 while ( remain ) 459 while ( remain )
460 { 460 {
461 Buffer_disable_immediate_removal( &this->stereo_buf ); 461 Buffer_disable_immediate_removal( &this->stereo_buf );
462 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain ); 462 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
463 if ( remain ) 463 if ( remain )
464 { 464 {
465 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) ) 465 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
466 { 466 {
467 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); 467 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
468 468
469 // Remute voices 469 // Remute voices
470 Sound_mute_voices( this, this->mute_mask_ ); 470 Sound_mute_voices( this, this->mute_mask_ );
471 } 471 }
472 int msec = Buffer_length( &this->stereo_buf ); 472 int msec = Buffer_length( &this->stereo_buf );
473 blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100; 473 blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
474 RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) ); 474 RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) );
475 assert( clocks_emulated ); 475 assert( clocks_emulated );
476 Buffer_end_frame( &this->stereo_buf, clocks_emulated ); 476 Buffer_end_frame( &this->stereo_buf, clocks_emulated );
477 } 477 }
478 } 478 }
479 return 0; 479 return 0;
480} 480}