001
002 package ibxm;
003
004 import java.io.*;
005
006 public class ScreamTracker3 {
007 private static final int[] effect_map = new int[] {
008 0xFF,
009 0x25, /* A: Set Speed.*/
010 0x0B, /* B: Pattern Jump.*/
011 0x0D, /* C: Pattern Break.*/
012 0x0A, /* D: Volume Slide.*/
013 0x02, /* E: Portamento Down.*/
014 0x01, /* F: Portamento Up.*/
015 0x03, /* G: Tone Portamento.*/
016 0x04, /* H: Vibrato.*/
017 0x1D, /* I: Tremor.*/
018 0x00, /* J: Arpeggio.*/
019 0x06, /* K: Vibrato + Volume Slide.*/
020 0x05, /* L: Tone Portamento + Volume Slide.*/
021 0xFF, /* M: */
022 0xFF, /* N: */
023 0x09, /* O: Sample Offset.*/
024 0xFF, /* P: */
025 0x1B, /* Q: Retrig + Volume Slide.*/
026 0x07, /* R: Tremolo.*/
027 0x0E, /* S: Extended Effects.*/
028 0x0F, /* T: Set Tempo.*/
029 0x24, /* U: Fine Vibrato.*/
030 0x10, /* V: Set Global Volume. */
031 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
032 0xFF, 0xFF, 0xFF, 0xFF
033 };
034
035 private static final int[] effect_s_map = new int[] {
036 0x00, /* 0: Set Filter.*/
037 0x03, /* 1: Glissando.*/
038 0x05, /* 2: Set Fine Tune.*/
039 0x04, /* 3: Set Vibrato Waveform.*/
040 0x07, /* 4: Set Tremolo Waveform.*/
041 0xFF, /* 5: */
042 0xFF, /* 6: */
043 0xFF, /* 7: */
044 0x08, /* 8: Set Panning.*/
045 0xFF, /* 9: */
046 0x09, /* A: Stereo Control.*/
047 0x06, /* B: Pattern Loop.*/
048 0x0C, /* C: Note Cut.*/
049 0x0D, /* D: Note Delay.*/
050 0x0E, /* E: Pattern Delay.*/
051 0x0F /* F: Invert Loop.*/
052 };
053
054 public static boolean is_s3m( byte[] header_96_bytes ) {
055 String s3m_identifier;
056 s3m_identifier = ascii_text( header_96_bytes, 44, 4 );
057 return s3m_identifier.equals( "SCRM" );
058 }
059
060 public static Module load_s3m( byte[] header_96_bytes, DataInput data_input ) throws IOException {
061 int num_pattern_orders, num_instruments, num_patterns, num_channels;
062 int flags, tracker_version, master_volume, panning, channel_config, sequence_length;
063 int instrument_idx, pattern_idx, channel_idx, order_idx, panning_offset;
064 boolean signed_samples, stereo_mode, default_panning;
065 int[] channel_map, sequence;
066 byte[] s3m_file;
067 Module module;
068 Instrument instrument;
069 s3m_file = read_s3m_file( header_96_bytes, data_input );
070 module = new Module();
071 module.song_title = ascii_text( s3m_file, 0, 28 );
072 num_pattern_orders = get_num_pattern_orders( s3m_file );
073 num_instruments = get_num_instruments( s3m_file );
074 num_patterns = get_num_patterns( s3m_file );
075 flags = unsigned_short_le( s3m_file, 38 );
076 tracker_version = unsigned_short_le( s3m_file, 40 );
077 if( ( flags & 0x40 ) == 0x40 || tracker_version == 0x1300 ) {
078 module.fast_volume_slides = true;
079 }
080 signed_samples = false;
081 if( unsigned_short_le( s3m_file, 42 ) == 0x01 ) {
082 signed_samples = true;
083 }
084 module.global_volume = s3m_file[ 48 ] & 0xFF;
085 module.default_speed = s3m_file[ 49 ] & 0xFF;
086 module.default_tempo = s3m_file[ 50 ] & 0xFF;
087 master_volume = s3m_file[ 51 ] & 0x7F;
088 module.channel_gain = ( master_volume << IBXM.FP_SHIFT ) >> 7;
089 stereo_mode = ( s3m_file[ 51 ] & 0x80 ) == 0x80;
090 default_panning = ( s3m_file[ 53 ] & 0xFF ) == 0xFC;
091 channel_map = new int[ 32 ];
092 num_channels = 0;
093 for( channel_idx = 0; channel_idx < 32; channel_idx++ ) {
094 channel_config = s3m_file[ 64 + channel_idx ] & 0xFF;
095 channel_map[ channel_idx ] = -1;
096 if( channel_config < 16 ) {
097 channel_map[ channel_idx ] = num_channels;
098 num_channels += 1;
099 }
100 }
101 module.set_num_channels( num_channels );
102 panning_offset = 96 + num_pattern_orders + num_instruments * 2 + num_patterns * 2;
103 for( channel_idx = 0; channel_idx < 32; channel_idx++ ) {
104 if( channel_map[ channel_idx ] < 0 ) continue;
105 panning = 7;
106 if( stereo_mode ) {
107 panning = 12;
108 if( ( s3m_file[ 64 + channel_idx ] & 0xFF ) < 8 ) {
109 panning = 3;
110 }
111 }
112 if( default_panning ) {
113 flags = s3m_file[ panning_offset + channel_idx ] & 0xFF;
114 if( ( flags & 0x20 ) == 0x20 ) {
115 panning = flags & 0xF;
116 }
117 }
118 module.set_initial_panning( channel_map[ channel_idx ], panning * 17 );
119 }
120 sequence = read_s3m_sequence( s3m_file );
121 module.set_sequence_length( sequence.length );
122 for( order_idx = 0; order_idx < sequence.length; order_idx++ ) {
123 module.set_sequence( order_idx, sequence[ order_idx ] );
124 }
125 module.set_num_instruments( num_instruments );
126 for( instrument_idx = 0; instrument_idx < num_instruments; instrument_idx++ ) {
127 instrument = read_s3m_instrument( s3m_file, instrument_idx, signed_samples );
128 module.set_instrument( instrument_idx + 1, instrument );
129 }
130 module.set_num_patterns( num_patterns );
131 for( pattern_idx = 0; pattern_idx < num_patterns; pattern_idx++ ) {
132 module.set_pattern( pattern_idx, read_s3m_pattern( s3m_file, pattern_idx, channel_map ) );
133 }
134 return module;
135 }
136
137 private static int[] read_s3m_sequence( byte[] s3m_file ) {
138 int num_pattern_orders, sequence_length;
139 int sequence_idx, order_idx, pattern_order;
140 int[] sequence;
141 num_pattern_orders = get_num_pattern_orders( s3m_file );
142 sequence_length = 0;
143 for( order_idx = 0; order_idx < num_pattern_orders; order_idx++ ) {
144 pattern_order = s3m_file[ 96 + order_idx ] & 0xFF;
145 if( pattern_order == 255 ) {
146 break;
147 } else if( pattern_order < 254 ) {
148 sequence_length += 1;
149 }
150 }
151 sequence = new int[ sequence_length ];
152 sequence_idx = 0;
153 for( order_idx = 0; order_idx < num_pattern_orders; order_idx++ ) {
154 pattern_order = s3m_file[ 96 + order_idx ] & 0xFF;
155 if( pattern_order == 255 ) {
156 break;
157 } else if( pattern_order < 254 ) {
158 sequence[ sequence_idx ] = pattern_order;
159 sequence_idx += 1;
160 }
161 }
162 return sequence;
163 }
164
165 private static Instrument read_s3m_instrument( byte[] s3m_file, int instrument_idx, boolean signed_samples ) {
166 int instrument_offset;
167 int sample_data_offset, sample_data_length;
168 int loop_start, loop_length, c2_rate, sample_idx, amplitude;
169 boolean sixteen_bit;
170 Instrument instrument;
171 Sample sample;
172 short[] sample_data;
173 instrument_offset = get_instrument_offset( s3m_file, instrument_idx );
174 instrument = new Instrument();
175 instrument.name = ascii_text( s3m_file, instrument_offset + 48, 28 );
176 sample = new Sample();
177 if( s3m_file[ instrument_offset ] == 1 ) {
178 sample_data_length = get_sample_data_length( s3m_file, instrument_offset );
179 loop_start = unsigned_short_le( s3m_file, instrument_offset + 20 );
180 loop_length = unsigned_short_le( s3m_file, instrument_offset + 24 ) - loop_start;
181 sample.volume = s3m_file[ instrument_offset + 28 ] & 0xFF;
182 if( s3m_file[ instrument_offset + 30 ] != 0 ) {
183 throw new IllegalArgumentException( "ScreamTracker3: Packed samples not supported!" );
184 }
185 if( ( s3m_file[ instrument_offset + 31 ] & 0x01 ) == 0 ) {
186 loop_length = 0;
187 }
188 if( ( s3m_file[ instrument_offset + 31 ] & 0x02 ) != 0 ) {
189 throw new IllegalArgumentException( "ScreamTracker3: Stereo samples not supported!" );
190 }
191 sixteen_bit = ( s3m_file[ instrument_offset + 31 ] & 0x04 ) != 0;
192 c2_rate = unsigned_short_le( s3m_file, instrument_offset + 32 );
193 sample.transpose = LogTable.log_2( c2_rate ) - LogTable.log_2( 8363 );
194 sample_data_offset = get_sample_data_offset( s3m_file, instrument_offset );
195 if( sixteen_bit ) {
196 if( signed_samples ) {
197 throw new IllegalArgumentException( "ScreamTracker3: Signed 16-bit samples not supported!" );
198 }
199 sample_data_length >>= 1;
200 sample_data = new short[ sample_data_length ];
201 for( sample_idx = 0; sample_idx < sample_data_length; sample_idx++ ) {
202 amplitude = s3m_file[ sample_data_offset + sample_idx * 2 ] & 0xFF;
203 amplitude |= ( s3m_file[ sample_data_offset + sample_idx * 2 + 1 ] & 0xFF ) << 8;
204 sample_data[ sample_idx ] = ( short ) ( amplitude - 32768 );
205 }
206 } else {
207 sample_data = new short[ sample_data_length ];
208 if( signed_samples ) {
209 for( sample_idx = 0; sample_idx < sample_data_length; sample_idx++ ) {
210 amplitude = s3m_file[ sample_data_offset + sample_idx ] << 8;
211 sample_data[ sample_idx ] = ( short ) amplitude;
212 }
213 } else {
214 for( sample_idx = 0; sample_idx < sample_data_length; sample_idx++ ) {
215 amplitude = ( s3m_file[ sample_data_offset + sample_idx ] & 0xFF ) << 8;
216 sample_data[ sample_idx ] = ( short ) ( amplitude - 32768 );
217 }
218 }
219 }
220 sample.set_sample_data( sample_data, loop_start, loop_length, false );
221 }
222 instrument.set_num_samples( 1 );
223 instrument.set_sample( 0, sample );
224 return instrument;
225 }
226
227 private static Pattern read_s3m_pattern( byte[] s3m_file, int pattern_idx, int[] channel_map ) {
228 int pattern_offset;
229 int num_channels, num_notes;
230 int row_idx, channel_idx, note_idx;
231 int token, key, volume_column, effect, effect_param;
232 byte[] pattern_data;
233 Pattern pattern;
234 num_channels = 0;
235 for( channel_idx = 0; channel_idx < 32; channel_idx++ ) {
236 if( channel_map[ channel_idx ] >= num_channels ) {
237 num_channels = channel_idx + 1;
238 }
239 }
240 num_notes = num_channels * 64;
241 pattern_data = new byte[ num_notes * 5 ];
242 row_idx = 0;
243 pattern_offset = get_pattern_offset( s3m_file, pattern_idx ) + 2;
244 while( row_idx < 64 ) {
245 token = s3m_file[ pattern_offset ] & 0xFF;
246 pattern_offset += 1;
247 if( token > 0 ) {
248 channel_idx = channel_map[ token & 0x1F ];
249 note_idx = ( num_channels * row_idx + channel_idx ) * 5;
250 if( ( token & 0x20 ) == 0x20 ) {
251 /* Key + Instrument.*/
252 if( channel_idx >= 0 ) {
253 key = s3m_file[ pattern_offset ] & 0xFF;
254 if( key == 255 ) {
255 key = 0;
256 } else if( key == 254 ) {
257 key = 97;
258 } else {
259 key = ( ( key & 0xF0 ) >> 4 ) * 12 + ( key & 0x0F ) + 1;
260 while( key > 96 ) {
261 key = key - 12;
262 }
263 }
264 pattern_data[ note_idx ] = ( byte ) key;
265 pattern_data[ note_idx + 1 ] = s3m_file[ pattern_offset + 1 ];
266 }
267 pattern_offset += 2;
268 }
269 if( ( token & 0x40 ) == 0x40 ) {
270 /* Volume.*/
271 if( channel_idx >= 0 ) {
272 volume_column = ( s3m_file[ pattern_offset ] & 0xFF ) + 0x10;
273 pattern_data[ note_idx + 2 ] = ( byte ) volume_column;
274 }
275 pattern_offset += 1;
276 }
277 if( ( token & 0x80 ) == 0x80 ) {
278 /* Effect + Param.*/
279 if( channel_idx >= 0 ) {
280 effect = s3m_file[ pattern_offset ] & 0xFF;
281 effect_param = s3m_file[ pattern_offset + 1 ] & 0xFF;
282 effect = effect_map[ effect & 0x1F ];
283 if( effect == 0xFF ) {
284 effect = 0;
285 effect_param = 0;
286 }
287 if( effect == 0x0E ) {
288 effect = effect_s_map[ ( effect_param & 0xF0 ) >> 4 ];
289 effect_param = effect_param & 0x0F;
290 switch( effect ) {
291 case 0x08:
292 effect = 0x08;
293 effect_param = effect_param * 17;
294 break;
295 case 0x09:
296 effect = 0x08;
297 if( effect_param > 7 ) {
298 effect_param -= 8;
299 } else {
300 effect_param += 8;
301 }
302 effect_param = effect_param * 17;
303 break;
304 case 0xFF:
305 effect = 0;
306 effect_param = 0;
307 break;
308 default:
309 effect_param = ( ( effect & 0x0F ) << 4 ) | ( effect_param & 0x0F );
310 effect = 0x0E;
311 break;
312 }
313 }
314 pattern_data[ note_idx + 3 ] = ( byte ) effect;
315 pattern_data[ note_idx + 4 ] = ( byte ) effect_param;
316 }
317 pattern_offset += 2;
318 }
319 } else {
320 row_idx += 1;
321 }
322 }
323 pattern = new Pattern();
324 pattern.num_rows = 64;
325 pattern.set_pattern_data( pattern_data );
326 return pattern;
327 }
328
329 private static byte[] read_s3m_file( byte[] header_96_bytes, DataInput data_input ) throws IOException {
330 int s3m_file_length;
331 int num_pattern_orders, num_instruments, num_patterns;
332 int instrument_idx, pattern_idx;
333 int instrument_offset, sample_data_offset, pattern_offset;
334 byte[] s3m_file;
335 if( !is_s3m( header_96_bytes ) ) {
336 throw new IllegalArgumentException( "ScreamTracker3: Not an S3M file!" );
337 }
338 s3m_file = header_96_bytes;
339 s3m_file_length = header_96_bytes.length;
340 num_pattern_orders = get_num_pattern_orders( s3m_file );
341 num_instruments = get_num_instruments( s3m_file );
342 num_patterns = get_num_patterns( s3m_file );
343 s3m_file_length += num_pattern_orders;
344 s3m_file_length += num_instruments * 2;
345 s3m_file_length += num_patterns * 2;
346 /* Read enough of file to calculate the length.*/
347 s3m_file = read_more( s3m_file, s3m_file_length, data_input );
348 for( instrument_idx = 0; instrument_idx < num_instruments; instrument_idx++ ) {
349 instrument_offset = get_instrument_offset( s3m_file, instrument_idx );
350 instrument_offset += 80;
351 if( instrument_offset > s3m_file_length ) {
352 s3m_file_length = instrument_offset;
353 }
354 }
355 for( pattern_idx = 0; pattern_idx < num_patterns; pattern_idx++ ) {
356 pattern_offset = get_pattern_offset( s3m_file, pattern_idx );
357 pattern_offset += 2;
358 if( pattern_offset > s3m_file_length ) {
359 s3m_file_length = pattern_offset;
360 }
361 }
362 s3m_file = read_more( s3m_file, s3m_file_length, data_input );
363 /* Read rest of file.*/
364 for( instrument_idx = 0; instrument_idx < num_instruments; instrument_idx++ ) {
365 instrument_offset = get_instrument_offset( s3m_file, instrument_idx );
366 sample_data_offset = get_sample_data_offset( s3m_file, instrument_offset );
367 sample_data_offset += get_sample_data_length( s3m_file, instrument_offset );
368 if( sample_data_offset > s3m_file_length ) {
369 s3m_file_length = sample_data_offset;
370 }
371 }
372 for( pattern_idx = 0; pattern_idx < num_patterns; pattern_idx++ ) {
373 pattern_offset = get_pattern_offset( s3m_file, pattern_idx );
374 pattern_offset += get_pattern_length( s3m_file, pattern_offset );
375 pattern_offset += 2;
376 if( pattern_offset > s3m_file_length ) {
377 s3m_file_length = pattern_offset;
378 }
379 }
380 s3m_file = read_more( s3m_file, s3m_file_length, data_input );
381 return s3m_file;
382 }
383
384 private static int get_num_pattern_orders( byte[] s3m_file ) {
385 int num_pattern_orders;
386 num_pattern_orders = unsigned_short_le( s3m_file, 32 );
387 return num_pattern_orders;
388 }
389
390 private static int get_num_instruments( byte[] s3m_file ) {
391 int num_instruments;
392 num_instruments = unsigned_short_le( s3m_file, 34 );
393 return num_instruments;
394 }
395
396 private static int get_num_patterns( byte[] s3m_file ) {
397 int num_patterns;
398 num_patterns = unsigned_short_le( s3m_file, 36 );
399 return num_patterns;
400 }
401
402 private static int get_instrument_offset( byte[] s3m_file, int instrument_idx ) {
403 int instrument_offset, pointer_offset;
404 pointer_offset = 96 + get_num_pattern_orders( s3m_file );
405 instrument_offset = unsigned_short_le( s3m_file, pointer_offset + instrument_idx * 2 ) << 4;
406 return instrument_offset;
407 }
408
409 private static int get_sample_data_offset( byte[] s3m_file, int instrument_offset ) {
410 int sample_data_offset;
411 sample_data_offset = 0;
412 if( s3m_file[ instrument_offset ] == 1 ) {
413 sample_data_offset = ( s3m_file[ instrument_offset + 13 ] & 0xFF ) << 20;
414 sample_data_offset |= unsigned_short_le( s3m_file, instrument_offset + 14 ) << 4;
415 }
416 return sample_data_offset;
417 }
418
419 private static int get_sample_data_length( byte[] s3m_file, int instrument_offset ) {
420 int sample_data_length;
421 boolean sixteen_bit;
422 sample_data_length = 0;
423 if( s3m_file[ instrument_offset ] == 1 ) {
424 sample_data_length = unsigned_short_le( s3m_file, instrument_offset + 16 );
425 sixteen_bit = ( s3m_file[ instrument_offset + 31 ] & 0x04 ) != 0;
426 if( sixteen_bit ) {
427 sample_data_length <<= 1;
428 }
429 }
430 return sample_data_length;
431 }
432
433 private static int get_pattern_offset( byte[] s3m_file, int pattern_idx ) {
434 int pattern_offset, pointer_offset;
435 pointer_offset = 96 + get_num_pattern_orders( s3m_file );
436 pointer_offset += get_num_instruments( s3m_file ) * 2;
437 pattern_offset = unsigned_short_le( s3m_file, pointer_offset + pattern_idx * 2 ) << 4;
438 return pattern_offset;
439 }
440
441 private static int get_pattern_length( byte[] s3m_file, int pattern_offset ) {
442 int pattern_length;
443 pattern_length = unsigned_short_le( s3m_file, pattern_offset );
444 return pattern_length;
445 }
446
447 private static byte[] read_more( byte[] old_data, int new_length, DataInput data_input ) throws IOException {
448 byte[] new_data;
449 new_data = old_data;
450 if( new_length > old_data.length ) {
451 new_data = new byte[ new_length ];
452 System.arraycopy( old_data, 0, new_data, 0, old_data.length );
453 try {
454 data_input.readFully( new_data, old_data.length, new_data.length - old_data.length );
455 } catch( EOFException e ) {
456 System.out.println( "ScreamTracker3: Module has been truncated!" );
457 }
458 }
459 return new_data;
460 }
461
462 private static int unsigned_short_le( byte[] buffer, int offset ) {
463 int value;
464 value = buffer[ offset ] & 0xFF;
465 value = value | ( ( buffer[ offset + 1 ] & 0xFF ) << 8 );
466 return value;
467 }
468
469 private static String ascii_text( byte[] buffer, int offset, int length ) {
470 int idx, chr;
471 byte[] string_buffer;
472 String string;
473 string_buffer = new byte[ length ];
474 for( idx = 0; idx < length; idx++ ) {
475 chr = buffer[ offset + idx ];
476 if( chr < 32 ) {
477 chr = 32;
478 }
479 string_buffer[ idx ] = ( byte ) chr;
480 }
481 try {
482 string = new String( string_buffer, 0, length, "ISO-8859-1" );
483 } catch( UnsupportedEncodingException e ) {
484 string = "";
485 }
486 return string;
487 }
488 }
489