dropped aas, moved to maxmod
[gbajam21] / tools / mmutil / mod.c
1 /****************************************************************************
2  *                                                          __              *
3  *                ____ ___  ____ __  ______ ___  ____  ____/ /              *
4  *               / __ `__ \/ __ `/ |/ / __ `__ \/ __ \/ __  /               *
5  *              / / / / / / /_/ />  </ / / / / / /_/ / /_/ /                *
6  *             /_/ /_/ /_/\__,_/_/|_/_/ /_/ /_/\____/\__,_/                 *
7  *                                                                          *
8  *         Copyright (c) 2008, Mukunda Johnson (mukunda@maxmod.org)         *
9  *                                                                          *
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.        *
13  *                                                                          *
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  ****************************************************************************/
22
23 // information from FMODDOC.TXT by FireLight
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <math.h>
28 #include "defs.h"
29 #include "mas.h"
30 #include "mod.h"
31 #include "xm.h"
32 #include "files.h"
33 #include "simple.h"
34 #include "errors.h"
35 #include "samplefix.h"
36
37 #ifdef SUPER_ASCII
38 #define vstr_mod_div "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\n"
39 #define vstr_mod_samp_top               "ÚÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\n"
40 #define vstr_mod_samp_header    "³INDEX³LENGTH³LOOP ³VOLUME³ MID-C ³ NAME                  ³\n"
41 #define vstr_mod_samp_slice             "ÃÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´\n"
42 #define vstr_mod_samp                   "³ %2i  ³%5i ³ %3s ³ %3i%% ³ %ihz³ %-22s³\n"
43 #define vstr_mod_samp_bottom    "ÀÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\n"
44 #define vstr_mod_pattern " \x0e %2i%s"
45 #else
46 #define vstr_mod_div "--------------------------------------------\n"
47 #define vstr_mod_samp_top               vstr_mod_div
48 #define vstr_mod_samp_header    " INDEX LENGTH LOOP  VOLUME  MID-C   NAME                   \n"
49 //#define vstr_mod_samp_slice           ""
50 #define vstr_mod_samp                   " %-2i    %-5i  %-3s   %3i%%    %ihz  %-22s \n"
51 #define vstr_mod_samp_bottom    vstr_mod_div
52 #define vstr_mod_pattern " * %2i%s"
53 #endif
54
55 #ifdef _MSC_VER
56 double round( double value )
57 {
58         return floor(value+0.5);
59 }
60 #endif
61
62 int Create_MOD_Instrument( Instrument* inst, u8 sample )
63 {
64         int x;
65         memset( inst, 0, sizeof( Instrument ) );
66         inst->global_volume = 128;
67         // setup notemap
68         for( x = 0; x < 120; x++ )
69         {
70                 inst->notemap[x] = x | ((sample+1)<<8);
71         }
72         return ERR_NONE;
73 }
74
75 int Load_MOD_SampleData( Sample* samp )
76 {
77         u32 t;
78         if( samp->sample_length > 0 )
79         {
80                 samp->data = (u8*)malloc( samp->sample_length ); // allocate a SAMPLE_LENGTH sized pointer to buffer in memory and load the sample into it
81                 for( t = 0; t < samp->sample_length; t++ )
82                 {
83                         ((u8*)samp->data)[t] = read8() + 128; // unsign data
84                 }
85         }
86         FixSample( samp );
87         return ERR_NONE;
88 }
89
90 int Load_MOD_Pattern( Pattern* patt, u8 nchannels, u8* inst_count )
91 {
92         u8 data1;
93         u8 data2;
94         u8 data3;
95         u8 data4;
96
97         u16 period;
98         u8 inst;
99         u8 effect;
100         u8 param;
101
102         u32 row;
103         u32 col;
104
105         PatternEntry* p;
106
107         memset( patt, 0, sizeof( Pattern ) );
108         patt->nrows = 64;                                               // MODs have fixed 64 rows per pattern
109
110         for( row = 0; row < 64*MAX_CHANNELS; row++ )
111         {
112                 patt->data[row].note = 250;
113         }
114         
115         for( row = 0; row < 64; row++ )
116         {
117                 for( col = 0; col < nchannels; col++ )
118                 {
119                         data1 = read8();        // +-------------------------------------+
120                         data2 = read8();        // | Byte 0    Byte 1   Byte 2   Byte 3  |
121                         data3 = read8();        // |-------------------------------------|
122                         data4 = read8();        // |aaaaBBBB CCCCCCCCC DDDDeeee FFFFFFFFF|
123                                                                 // +-------------------------------------+
124
125                         period = (data1&0xf)*256 + (data2);     // BBBBCCCCCCCC = sample period value
126                         inst = (data1&0xF0)+(data3>>4);         // aaaaDDDD     = sample number
127                         effect = data3&0xF;                                     // eeee         = effect number
128                         param = data4;                                          // FFFFFFFF     = effect parameters
129                         
130                         // fix parameter for certain MOD effects
131                         switch( effect )
132                         {
133                         case 5: // 5xy glis+slide
134                         case 6: // 6xy vib+slide
135                                 if( param & 0xF0 )      // clear Y if X
136                                         param &= 0xF0;
137                         }
138                         
139                         p = &patt->data[row*MAX_CHANNELS+col];  // copy data to pattern entry
140                         p->inst = inst;                                                 // ...
141                         CONV_XM_EFFECT( &effect, &param );              //  ...
142                         p->fx = effect;                                                 //   ...
143                         p->param = param;                                               //    ...
144                         
145                         if( period != 0 )                                               // 0 = no note, otherwise calculate note value from the amiga period
146                                 p->note = (int)round(12.0*log( (856.0)/(double)period )/log(2)) + 37 + 11;
147                         if( *inst_count < (inst + 1) )
148                         {
149                                 *inst_count = (inst + 1);
150                                 if( *inst_count > 31 )
151                                         *inst_count = 31;
152                         }
153                 }
154         }
155         return ERR_NONE;
156 }
157
158 int Load_MOD_Sample( Sample* samp, bool verbose, int index )
159 {
160         int finetune;
161         int x;
162
163         memset( samp, 0, sizeof( Sample ) );
164         samp->msl_index = 0xFFFF;
165         for( x = 0; x < 22; x++ )
166                 samp->name[x] = read8();                                                                        // read in 22 bytes, store as SAMPLE_NAME
167         for( x = 0; x < 12; x++ )                               // copy to filename
168                 samp->filename[x] = samp->name[x];
169         samp->sample_length = (read8()*256 + read8()) * 2;                              // read in 2 bytes (word), store as SAMPLE_LENGTH
170         finetune = read8();                                                                                             // read in 1 byte,         store as FINE_TUNE
171         if( finetune >= 8 ) finetune -= 16;
172         
173         samp->default_volume = read8();                                                                 // read in 1 byte,         store as VOLUME
174         samp->loop_start = (read8()*256 + read8()) * 2;                                 // read in 2 bytes (word), store as LOOP_START
175         samp->loop_end = samp->loop_start + (read8()*256+read8())*2;    // read in 2 bytes (word), store as LOOP_LENGTH
176
177         // IS THIS WRONG?? :
178         samp->frequency = (int)(8363.0 * pow( 2.0, ((double)finetune) * (1.0/192.0) ) );        // calculate frequency...
179
180         samp->global_volume=64;                                                                                 // max global volume
181         if( (samp->loop_end - samp->loop_start) <= 2 )                                  // if loop length <= 2 then disabled loop
182         {
183                 samp->loop_type = samp->loop_start = samp->loop_end = 0;
184         }
185         else
186         {
187                 samp->loop_type = 1;                                                                                    // otherwise enable
188         }
189         if( verbose )
190         {
191                 if( samp->sample_length != 0 )
192                 {
193                         //printf( "%i   %s      %i%%    %ihz\n", samp->sample_length, samp->loop_type != 0 ? "Yes" : "No", (samp->default_volume*100)/64, samp->frequency );
194                         printf( vstr_mod_samp, index, samp->sample_length, samp->loop_type != 0 ? "Yes" : "No", (samp->default_volume*100)/64, samp->frequency, samp->name );
195                         /*
196                         printf( "  Length......%i\n", samp->sample_length );
197                         if( samp->loop_type != 0 )
198                         {
199                                 printf( "  Loop........%i->%i\n", samp->loop_start, samp->loop_end );
200                         }
201                         else
202                         {
203                                 printf( "  Loop........None\n" );
204                         }
205                         printf( "  Volume......%i\n", samp->default_volume );
206                         printf( "  Middle C....%ihz\n", samp->frequency );*/
207                 }
208                 else
209                 {
210                         //printf( "---\n" );
211                 }
212         }
213         return ERR_NONE;
214 }
215
216 int Load_MOD( MAS_Module* mod, bool verbose )
217 {
218         u32 file_start;
219         u32 mod_channels;
220         int x;
221
222         int npatterns;
223
224         u32 sig;
225         char sigs[5];
226
227         if( verbose )
228                 printf( "Loading MOD, " );
229
230         memset( mod, 0, sizeof( MAS_Module ) );
231         file_start = file_tell_read();
232         file_seek_read( 0x438, SEEK_SET );      // Seek to offset 1080 (438h) in the file
233         sig = read32();                                         // read in 4 bytes
234         sigs[0]=sig&0xFF;
235         sigs[1]=(sig>>8)&0xFF;
236         sigs[2]=(sig>>16)&0xFF;
237         sigs[3]=(sig>>24);
238         sigs[4]=0;
239         switch( sig )
240         {
241         case 'NHC1':
242                 mod_channels=1;
243                 break;
244         case 'NHC2':
245                 mod_channels=2;
246                 break;
247         case 'NHC3':
248                 mod_channels=3;
249                 break;
250         case '.K.M':                                            // compare them to "M.K."  - if true we have a 4 channel mod
251         case 'NHC4':
252                 mod_channels=4;
253                 break;
254         case 'NHC5':
255                 mod_channels=5;
256                 break;
257         case 'NHC6':
258                 mod_channels=6;                                 // compare them to "6CHN"  - if true we have a 6 channel mod
259                 break;
260         case 'NHC7':
261                 mod_channels=7;
262                 break;
263         case 'NHC8':                                            // compare them to "8CHN"  - if true we have an 8 channel mod
264                 mod_channels=8;
265                 break;
266         case 'NHC9':
267                 mod_channels=9;
268                 break;
269         default:
270                 if( sig>>16 == 'HC' )                   // There are also rare tunes that use **CH where ** = 10-32 channels
271                 {
272                         char chn_number[3];
273                         chn_number[0] = (char)(sig&0xFF);
274                         chn_number[1] = (char)((sig>>8)&0xFF);
275                         chn_number[2] = 0;
276                         mod_channels = atoi( chn_number );
277                         if( mod_channels > MAX_CHANNELS  )
278                                 return ERR_MANYCHANNELS;
279                 }
280                 else
281                 {
282                         return ERR_INVALID_MODULE;      // otherwise exit and display error message.
283                 }
284         }
285
286         file_seek_read( file_start, SEEK_SET ); // - Seek back to position 0, the start of the file
287         for( x = 0; x < 20; x++ )
288                 mod->title[x] = read8();                        // - read in 20 bytes, store as MODULE_NAME.
289
290         if( verbose )
291         {
292                 printf( "\"%s\"\n", mod->title );
293                 printf( "%i channels (%s)\n", mod_channels, sigs );
294         }
295         
296         for( x = 0; x < MAX_CHANNELS; x++ )
297         {
298                 if( (x&3)!=1 && (x&3) != 2 )
299                         mod->channel_panning[x] = clamp_u8( 128 - (PANNING_SEP/2) );
300                 else
301                         mod->channel_panning[x] = clamp_u8( 128 + (PANNING_SEP/2) );
302                 mod->channel_volume[x] = 64;
303         }
304         
305         // set MOD settings
306         mod->freq_mode = 0;
307         mod->global_volume = 64;
308         mod->initial_speed = 6;
309         mod->initial_tempo = 125;
310         mod->inst_count = 0; // filled in by Load_MOD_Pattern
311         mod->inst_mode = false;
312         mod->instruments = (Instrument*)malloc( 31 * sizeof( Instrument ) );
313         mod->link_gxx = false;
314         mod->old_effects = true;
315         mod->restart_pos = 0;
316         mod->samp_count = 0; // filled in before Load_MOD_SampleData
317         mod->samples = (Sample*)malloc( 31 * sizeof( Sample ) );
318         mod->stereo = true;
319         mod->xm_mode = true;
320         mod->old_mode=true;
321         
322         if( verbose )
323         {
324                 printf( vstr_mod_div );
325                 printf( "Loading Samples...\n" );
326                 printf( vstr_mod_samp_top );
327                 printf( vstr_mod_samp_header );
328 #ifdef vstr_mod_samp_slice
329                 printf( vstr_mod_samp_slice );
330 #endif
331         }
332         // Load Sample Information
333         for( x = 0; x < 31; x++ )
334         {
335         //      if( verbose )
336                         //printf( "Loading Sample %i...\n", x+1 );
337                 Create_MOD_Instrument( &mod->instruments[x], (u8)x );
338                 Load_MOD_Sample( &mod->samples[x], verbose, x );
339         }
340         
341         // read sequence
342         mod->order_count = read8();     // read a byte, store as SONG_LENGTH (this is the number of orders in a song)
343         mod->restart_pos = read8();     // read a byte, discard it (this is the UNUSED byte - used to be used in PT as the restart position, but not now since jump to pattern was introduced)
344         if( mod->restart_pos >= 127 )
345                 mod->restart_pos=0;
346         npatterns=0;                            // set NUMBER_OF_PATTERNS to equal 0......... or -1 :)
347         for( x = 0; x < 128; x++ )      // from this point, loop 128 times
348         {
349                 mod->orders[x] = read8();                       // read 1 byte, store it as ORDER <loopcounter>
350                 if( mod->orders[x] >= npatterns )       // if this value was bigger than NUMBER_OF_PATTERNS then set it to that value.
351                         npatterns=mod->orders[x]+1;
352         }
353         
354         read32();                                                               // read 4 bytes, discard them (we are at position 1080 again, this is M.K. etc!)
355         mod->patt_count = npatterns;
356         mod->patterns = (Pattern*)malloc( mod->patt_count * sizeof( Pattern ) );        // allocate patterns
357
358         if( verbose )
359         {
360                 printf( vstr_mod_samp_bottom );
361                 printf( "Sequence has %i entries.\n", mod->order_count );
362                 printf( "Module has %i pattern%s.\n", mod->patt_count, mod->patt_count==1?"":"s" );
363                 printf( vstr_mod_div );
364                 printf( "Loading Patterns...\n" );
365                 printf( vstr_mod_div );
366         }
367         
368         // Load Patterns
369         for( x = 0; x < mod->patt_count; x++ )
370         {
371                 if( verbose )
372                 {
373                         printf( vstr_mod_pattern, x+1, ((x+1)%15)?"":"\n" );
374                 }
375                 Load_MOD_Pattern( &mod->patterns[x], (u8)mod_channels, &(mod->inst_count) );
376         }
377         if( verbose )
378         {
379                 printf( "\n" );
380                 printf( vstr_mod_div );
381         }
382         // Load Sample Data
383         if( verbose )
384                 printf( "Loading Sample Data...\n" );
385         mod->samp_count = mod->inst_count;
386         for( x = 0; x < 31; x++ )
387         {
388                 Load_MOD_SampleData( &mod->samples[x] );
389         }
390         if( verbose )
391                 printf( vstr_mod_div );
392         return ERR_NONE;
393 }