CPLoader::Error CPLoader_S3M::load_sample(CPSample *p_sample) { int type = file->get_byte(); char filename[13]; file->get_byte_array((uint8_t *)filename, 12); filename[12] = 0; uint32_t samplepos = (uint32_t)file->get_byte() << 16; samplepos |= file->get_word(); samplepos *= 16; // printf("sample at %i\n",samplepos); /**/ int sample_size = file->get_dword(); int loop_begin = file->get_dword(); int loop_end = file->get_dword(); int def_volume = file->get_byte(); ; int dsk = file->get_byte(); int pack = file->get_byte(); int flags = file->get_byte(); int c2speed = file->get_dword(); file->get_dword(); //useless crap file->get_dword(); file->get_dword(); char name[29]; file->get_byte_array((uint8_t *)name, 28); name[28] = 0; p_sample->set_default_volume(def_volume); p_sample->set_name(name); char scrs[5]; file->get_byte_array((uint8_t *)scrs, 4); scrs[4] = 0; bool data_is_16bits = flags & 4; bool data_is_stereo = flags & 2; if (type == 0) { //empty sample return FILE_OK; } if ((type != 1) || scrs[0] != 'S' || scrs[1] != 'C' || scrs[2] != 'R' || scrs[3] != 'S') { // printf("type: %i, %c%c%c%c\n",type,scrs[0],scrs[1],scrs[2],scrs[3]); CP_PRINTERR("Not an S3M CPSample!"); return FILE_CORRUPTED; } //p_sample->data.set_c5_freq(p_sample->c2spd<<1); file->seek(samplepos); int real_sample_size = sample_size << BITBOOL(data_is_16bits); real_sample_size <<= BITBOOL(data_is_stereo); CPSampleManager *sm = CPSampleManager::get_singleton(); CPSample_ID id = sm->create(data_is_16bits, data_is_stereo, sample_size); if (id.is_null()) return FILE_OUT_OF_MEMORY; sm->lock_data(id); void *dataptr = sm->get_data(id); int chans = (data_is_stereo ? 2 : 1); for (int c = 0; c < chans; c++) { for (int i = 0; i < sample_size; i++) { if (data_is_16bits) { uint16_t s = file->get_word(); s -= 32768; //toggle sign int16_t *v = (int16_t *)&s; ((int16_t *)dataptr)[i * chans + c] = *v; } else { int8_t *v; uint8_t s = file->get_byte(); s -= 128; //toggle sign v = (int8_t *)&s; ((int8_t *)dataptr)[i * chans + c] = *v; } } } sm->unlock_data(id); sm->set_loop_begin(id, loop_begin); sm->set_loop_end(id, loop_end); sm->set_loop_type(id, (flags & 1) ? CP_LOOP_FORWARD : CP_LOOP_NONE); sm->set_c5_freq(id, c2speed << 1); p_sample->set_sample_data(id); /* Scream tracker previous to 3.10 seems to be buggy, as in, wont save what is after the sample loop, including the loop end point. Because of this I must fix it by habd */ if (flags & 1) { for (int c = 0; c < (data_is_stereo ? 2 : 1); c++) { sm->set_data(id, loop_end, sm->get_data(id, loop_begin, c), c); } } return FILE_OK; }
CPLoader::Error CPLoader_IT::load_instrument(CPInstrument *p_instrument,int *p_samples) { char aux_header[4]; file->get_byte_array((uint8_t*)aux_header,4); if ( aux_header[0]!='I' || aux_header[1]!='M' || aux_header[2]!='P' || aux_header[3]!='I') { CP_PRINTERR("IT CPLoader CPInstrument: Failed Identifier"); return FILE_UNRECOGNIZED; } // Ignore deprecated 8.3 filename field for (int i=0;i<12;i++) file->get_byte(); //Ignore zerobyte file->get_byte(); /* (byte) CPInstrument type (always 0) */ switch( file->get_byte() ) { /* New CPNote Action [0,1,2,3] */ case 0: p_instrument->set_NNA_type( CPInstrument::NNA_NOTE_CUT ) ; break; case 1: p_instrument->set_NNA_type( CPInstrument::NNA_NOTE_CONTINUE ) ; break; case 2: p_instrument->set_NNA_type( CPInstrument::NNA_NOTE_OFF ) ; break; case 3: p_instrument->set_NNA_type( CPInstrument::NNA_NOTE_FADE ) ; break; }; switch( file->get_byte() ) { // Duplicate Check Type case 0: p_instrument->set_DC_type( CPInstrument::DCT_DISABLED ); break ; case 1: p_instrument->set_DC_type( CPInstrument::DCT_NOTE ); break ; case 2: p_instrument->set_DC_type( CPInstrument::DCT_SAMPLE ); break ; case 3: p_instrument->set_DC_type( CPInstrument::DCT_INSTRUMENT ); break ; } switch( file->get_byte() ) { //Duplicate Check Action case 0: p_instrument->set_DC_action( CPInstrument::DCA_NOTE_CUT ); break ; case 1: p_instrument->set_DC_action( CPInstrument::DCA_NOTE_OFF ); break ; case 2: p_instrument->set_DC_action( CPInstrument::DCA_NOTE_FADE ); break ; } int fade = file->get_word(); //intf("AFADE: %i\n",fade); if (fade>CPInstrument::MAX_FADEOUT) //needs to be clipped because of horrible modplug doings fade=CPInstrument::MAX_FADEOUT; p_instrument->set_volume_fadeout( fade ); p_instrument->set_pan_pitch_separation( file->get_byte() ); p_instrument->set_pan_pitch_center( file->get_byte() ); p_instrument->set_volume_global_amount( file->get_byte() ); uint8_t pan=file->get_byte(); p_instrument->set_pan_default_amount(pan&0x7F); p_instrument->set_pan_default_enabled( !(pan&0x80) ); p_instrument->set_volume_random_variation( file->get_byte() ); p_instrument->set_pan_random_variation( file->get_byte() ); file->get_word(); //empty (version) uint8_t samples=file->get_byte(); if (p_samples) *p_samples=samples; file->get_byte(); //empty char aux_name[26]; file->get_byte_array((uint8_t*)aux_name,26); p_instrument->set_name(aux_name); uint8_t cutoff=file->get_byte(); p_instrument->set_filter_default_cutoff(cutoff&0x7F); p_instrument->set_filter_use_default_cutoff(cutoff&0x80); uint8_t resonance=file->get_byte(); p_instrument->set_filter_default_resonance(resonance&0x7F); p_instrument->set_filter_use_default_resonance(resonance&0x80); file->get_dword(); //MIDI, IGNORED! /* CPNote -> CPSample table */ for (uint8_t i=0;i<CPNote::NOTES;i++) { uint8_t note=file->get_byte(); if (note>=CPNote::NOTES) note=0; p_instrument->set_note_number(i,note); uint8_t samp=file->get_byte(); if (samp==0 || samp>99) samp=CPNote::EMPTY; else samp--; p_instrument->set_sample_number(i,samp); } load_envelope( p_instrument->get_volume_envelope() ); load_envelope( p_instrument->get_pan_envelope() ); bool use_as_filter; load_envelope( p_instrument->get_pitch_filter_envelope(), &use_as_filter ); p_instrument->set_pitch_use_as_filter( use_as_filter ); return FILE_OK; }