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