    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