1 /****************************************************************************
3 * ____ ___ ____ __ ______ ___ ____ ____/ / *
4 * / __ `__ \/ __ `/ |/ / __ `__ \/ __ \/ __ / *
5 * / / / / / / /_/ /> </ / / / / / /_/ / /_/ / *
6 * /_/ /_/ /_/\__,_/_/|_/_/ /_/ /_/\____/\__,_/ *
8 * Copyright (c) 2008, Mukunda Johnson (mukunda@maxmod.org) *
10 * Permission to use, copy, modify, and/or distribute this software for any *
11 * purpose with or without fee is hereby granted, provided that the above *
12 * copyright notice and this permission notice appear in all copies. *
14 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES *
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF *
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR *
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES *
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN *
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *
20 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *
21 ****************************************************************************/
36 static int CalcEnvelopeSize( Instrument_Envelope* env )
38 return (env->node_count*4) + 8;
41 static int CalcInstrumentSize( Instrument* instr )
45 if( instr->env_flags & 1 ) // volume envelope exists
46 size += CalcEnvelopeSize( &instr->envelope_volume );
47 if( instr->env_flags & 2 ) // panning envelope exists
48 size += CalcEnvelopeSize( &instr->envelope_pan );
49 if( instr->env_flags & 4 ) // pitch envelope exists
50 size += CalcEnvelopeSize( &instr->envelope_pitch );
54 void Write_Instrument_Envelope( Instrument_Envelope* env )
57 write8( (u8)(env->node_count*4 + 8) ); // maximum is 6+75
58 write8( env->loop_start );
59 write8( env->loop_end );
60 write8( env->sus_start );
61 write8( env->sus_end );
62 write8( env->node_count );
63 write8( env->env_filter );
64 write8( BYTESMASHER );
65 if( env->node_count > 1 )
70 for( x = 0; x < env->node_count; x++ )
72 base = env->node_y[x];
73 if( x != env->node_count-1 )
76 range = env->node_x[x+1] - env->node_x[x];
77 if( range > 511 ) range = 511;
78 if( range < 1 ) range = 1;
79 delta = (((env->node_y[x+1] - base) * 512) + (range/2)) / range;
80 if( delta > 32767 ) delta = 32767;
81 if( delta < -32768 ) delta = -32768;
82 while( (base+ ((delta*range)>>9)) > 64 ) delta--;
83 while( (base+ ((delta*range)>>9)) < 0 ) delta++;
90 write16( (u16)delta );
91 write16( (u16)(base | (range<<7)) );
96 void Write_Instrument( Instrument* inst )
100 int first_notemap_samp;
102 inst->parapointer = file_tell_write()-MAS_OFFSET;
103 /*write8( inst->global_volume );
104 write8( (u8)inst->fadeout );
105 write8( inst->random_volume );
109 write8( inst->env_flags );
110 write8( inst->setpan );*/
112 write8( inst->global_volume );
113 write8( (u8)inst->fadeout );
114 write8( inst->random_volume );
117 write8( inst->env_flags );
118 write8( inst->setpan );
122 first_notemap_samp = (inst->notemap[0] >> 8);
123 for( y = 0; y < 120; y++ )
125 if( ((inst->notemap[y] & 0xFF) != y) ||
126 ((inst->notemap[y] >> 8) != first_notemap_samp) )
137 write16( (u16)CalcInstrumentSize( inst ) );
141 // single notemap entry
142 write16( (u16)(0x8000 | first_notemap_samp) );
145 write16( 0 ); // reserved space
147 if( inst->env_flags & 1 ) // write volume envelope
148 Write_Instrument_Envelope( &inst->envelope_volume );
149 if( inst->env_flags & 2 ) // write panning envelope
150 Write_Instrument_Envelope( &inst->envelope_pan );
151 if( inst->env_flags & 4 ) // write pitch envelope
152 Write_Instrument_Envelope( &inst->envelope_pitch );
156 for( y = 0; y < 120; y++ )
157 write16( inst->notemap[y] );
161 void Write_SampleData( Sample* samp )
164 u32 sample_length = samp->sample_length;
165 u32 sample_looplen = samp->loop_end - samp->loop_start;
167 if( target_system == SYSTEM_GBA )
169 write32( sample_length );
170 write32( samp->loop_type ? sample_looplen : 0xFFFFFFFF );
171 write8( SAMP_FORMAT_U8 );
172 write8( BYTESMASHER );
173 write16( (u16) ((samp->frequency * 1024 + (15768/2)) / 15768) );
178 if( samp->format & SAMPF_16BIT )
180 if( samp->loop_type )
182 write32( samp->loop_start / 2 );
183 write32( (samp->loop_end-samp->loop_start) / 2 );
188 write32( sample_length/2 );
193 if( samp->loop_type )
195 write32( samp->loop_start / 4 );
196 write32( (samp->loop_end-samp->loop_start) / 4 );
201 write32( sample_length/4 );
204 write8( sample_dsformat( samp ) );
205 write8( sample_dsreptype( samp ) );
206 write16( (u16) ((samp->frequency * 1024 + (32768/2)) / 32768) );
211 if( samp->format & SAMPF_16BIT )
213 for( x = 0; x < sample_length; x++ )
214 write16( ((u16*)samp->data)[x] );
217 if( samp->loop_type )
219 write16( ((u16*)samp->data)[samp->loop_start] );
220 write16( ((u16*)samp->data)[samp->loop_start+1] );
230 for( x = 0; x < sample_length; x++ )
231 write8( ((u8*)samp->data)[x] );
234 if( samp->loop_type )
236 write8( ((u8*)samp->data)[samp->loop_start] );
237 write8( ((u8*)samp->data)[samp->loop_start+1] );
238 write8( ((u8*)samp->data)[samp->loop_start+2] );
239 write8( ((u8*)samp->data)[samp->loop_start+3] );
243 for ( x = 0; x < 4; x++ )
244 write8( (target_system == SYSTEM_GBA) ? 128 : 0 );
249 void Write_Sample( Sample* samp )
251 align32(); // align data by 32 bits
252 samp->parapointer = file_tell_write()-MAS_OFFSET;
254 write8( samp->default_volume );
255 write8( samp->default_panning );
256 write16( (u16)(samp->frequency/4) );
257 write8( samp->vibtype );
258 write8( samp->vibdepth );
259 write8( samp->vibspeed );
260 write8( samp->global_volume );
261 write16( samp->vibrate );
263 write16( samp->msl_index );
265 if( samp->msl_index == 0xFFFF )
266 Write_SampleData(samp);
269 void Write_Pattern( Pattern* patt, bool xm_vol )
274 u16 last_mask[MAX_CHANNELS];
275 u16 last_note[MAX_CHANNELS];
276 u16 last_inst[MAX_CHANNELS];
277 u16 last_vol[MAX_CHANNELS];
278 u16 last_fx[MAX_CHANNELS];
279 u16 last_param[MAX_CHANNELS];
288 patt->parapointer = file_tell_write()-MAS_OFFSET;
289 write8( (u8)(patt->nrows-1) );
291 patt->cmarks[0] = true;
292 emptyvol = xm_vol ? 0 : 255;
294 // using IT pattern compression
296 for( row = 0; row < patt->nrows; row++ )
298 if( patt->cmarks[row] )
300 for( col=0;col<MAX_CHANNELS;col++ )
302 last_mask[col] = 256; // row is marked, clear previous data
303 last_note[col] = 256;
304 last_inst[col] = 256;
307 last_param[col] = 256;
310 for( col = 0; col < MAX_CHANNELS; col++ )
312 pe = &patt->data[row*MAX_CHANNELS+col];
313 if( ((pe->note != 250) || (pe->inst != 0) || (pe->vol != emptyvol) || (pe->fx != 0) || (pe->param != 0)) )
317 if( pe->note != 250 )
323 if( pe->note > 250 ) // noteoff/cut disabled start+reset
326 if( pe->vol != emptyvol )
329 if( pe->fx != 0 || pe->param != 0 )
334 if( pe->note == last_note[col] )
340 last_note[col] = pe->note;
341 if( last_note[col] == 254 || last_note[col] == 255 ) // DONT LET NOTEOFF/NOTECUT USE PREVIOUS PARAMETERS!
342 last_note[col] = 256;
348 if( pe->inst == last_inst[col] )
354 last_inst[col] = pe->inst;
360 if( pe->vol == last_vol[col] )
366 last_vol[col] = pe->vol;
372 if( (pe->fx == last_fx[col]) && (pe->param == last_param[col]) )
378 last_fx[col] = pe->fx;
379 last_param[col] = pe->param;
383 if( maskvar != last_mask[col] )
386 last_mask[col] = maskvar;
414 void Mark_Pattern_Row( MAS_Module* mod, int order, int row )
420 if( mod->orders[order] == 255 )
422 while( mod->orders[order] >= 254 )
424 if( mod->orders[order] == 255 )
426 if( mod->orders[order] == 254 )
429 p = &(mod->patterns[mod->orders[order]]);
430 p->cmarks[row] = true;
433 void Mark_Patterns( MAS_Module* mod )
443 for( o = 0; o < mod->order_count; o++ )
450 if( p >= mod->patt_count )
452 for( row = 0; row < mod->patterns[p].nrows; row++ )
454 for( col = 0; col < MAX_CHANNELS; col++ )
456 pe = &(mod->patterns[p].data[row*MAX_CHANNELS+col]);
457 if( pe->fx == 3 ) // PATTERN BREAK
459 if( pe->param != 0 ) // if param != 0 then mark next pattern
461 Mark_Pattern_Row( mod, o+1, pe->param );
464 else if( pe->fx == 19 )
466 if( pe->param == 0xB0 )
468 Mark_Pattern_Row( mod, o, row );
476 int Write_MAS( MAS_Module* mod, bool verbose, bool msl_dep )
483 // bool unique=false;
485 file_get_byte_count();
487 write32( BYTESMASHER );
488 write8( MAS_TYPE_SONG );
489 write8( MAS_VERSION );
490 write8( BYTESMASHER );
491 write8( BYTESMASHER );
493 MAS_OFFSET = file_tell_write();
495 write8( (u8)mod->order_count );
496 write8( mod->inst_count );
497 write8( mod->samp_count );
498 write8( mod->patt_count );
499 write8( (u8)((mod->link_gxx ? 1 : 0) | (mod->old_effects ? 2 : 0) | (mod->freq_mode ? 4 : 0) | (mod->xm_mode ? 8 : 0) | (msl_dep ? 16 : 0) | (mod->old_mode ? 32 : 0)) );
500 write8( mod->global_volume );
501 write8( mod->initial_speed );
502 write8( mod->initial_tempo );
503 write8( mod->restart_pos );
505 /* for( x = 0; x < mod->samp_count; x++ )
508 for( y = x-1; y >= 0; y-- )
510 if( mod->samples[x].msl_index == mod->samples[y].msl_index )
512 mod->samples[x].rsamp_index = mod->samples[y].rsamp_index;
519 rsamps[rsamp]=mod->samples[x].msl_index;
520 mod->samples[x].rsamp_index = rsamp;
525 write8( BYTESMASHER );
526 write8( BYTESMASHER );write8( BYTESMASHER );
527 for( x = 0; x < MAX_CHANNELS; x++ )
528 write8( mod->channel_volume[x] );
529 for( x = 0; x < MAX_CHANNELS; x++ )
530 write8( mod->channel_panning[x] );
531 for( x = 0; x < mod->order_count; x++ )
533 if( mod->orders[x] < 254 )
535 if( mod->orders[x] < mod->patt_count )
536 write8( mod->orders[x] );
542 write8( mod->orders[x] );
545 for( ; x < 200; x++ )
547 // reserve space for offsets
548 fpos_pointer = file_tell_write();
549 for( x = 0; x < mod->inst_count*4+mod->samp_count*4+mod->patt_count*4; x++ )
550 write8( BYTESMASHER ); // BA BA BLACK SHEEP
551 /* if( msl_dep && target_system == SYSTEM_NDS )
553 for( x = 0; x < rsamp; x++ ) // write sample indeces
554 write16( rsamps[x] );
559 printf("Header: %i bytes\n", file_get_byte_count() );
561 for( x = 0; x < mod->inst_count; x++ )
562 Write_Instrument( &mod->instruments[x] );
566 for( x = 0; x < mod->samp_count; x++ )
567 Write_Sample( &mod->samples[x] );
570 printf("Instruments: %i bytes\n", file_get_byte_count() );
572 Mark_Patterns( mod );
573 for( x = 0; x < mod->patt_count; x++ )
575 // for( y = 0; y < mod->order_count; y++ )
577 // if( mod->orders[y] == x )
578 Write_Pattern( &mod->patterns[x], mod->xm_mode );
584 printf("Patterns: %i bytes\n", file_get_byte_count() );
585 MAS_FILESIZE = file_tell_write() - MAS_OFFSET;
586 file_seek_write( MAS_OFFSET-8, SEEK_SET );
587 write32( MAS_FILESIZE );
588 file_seek_write( fpos_pointer, SEEK_SET );
589 for( x = 0; x < mod->inst_count; x++ )
590 write32( mod->instruments[x].parapointer );
591 for( x = 0; x < mod->samp_count; x++ )
593 printf("sample %s is at %d/%d of %d\n", mod->samples[x].name, mod->samples[x].parapointer,
594 file_tell_write(), mod->samples[x].sample_length);
595 write32( mod->samples[x].parapointer );
597 for( x = 0; x < mod->patt_count; x++ )
598 write32( mod->patterns[x].parapointer );
602 void Delete_Module( MAS_Module* mod )
605 if( mod->instruments )
606 free( mod->instruments );
609 for( x = 0; x < mod->samp_count; x++ )
611 if( mod->samples[x].data )
612 free( mod->samples[x].data );
614 free( mod->samples );
618 free( mod->patterns );