1 #include "config.h"
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <getopt.h>
5 #include <string.h>
6 #include <stdio.h>
7 #include <sys/mman.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
11 #include "types.h"
12
13 #define roundup(x,y) (((x) + (y) - 1) & ~((y) - 1))
14
15 int usecolor = 0;
16 int savesamples = 0;
17 FILE *savepatterns = 0;
18
19 char *FONT_RESET = "";
20 char *FONT_BRIGHT_BLACK = "";
21 char *FONT_BRIGHT_RED = "";
22 char *FONT_BRIGHT_GREEN = "";
23 char *FONT_BRIGHT_YELLOW = "";
24 char *FONT_BRIGHT_BLUE = "";
25 char *FONT_BRIGHT_PURPLE = "";
26 char *FONT_BRIGHT_CYAN = "";
27
28 #if 0
29
30 struct
31 {
32 uint32_t offset;
33 uint16_t length;
34 } Instruments[31];
35
36 #if 0
37 typedef struct __attribute__((packed))
38 {
39 char name[20];
40 char tracker[8];
41 uint8_t sig,type;
42 uint8_t maj, min;
43 uint8_t it, pats, gv;
44 char reserved[13];
45 } FileHeader;
46 #endif
47
48 #endif
49
DumpPrefix(unsigned char * mem,int len,int base,int baselen)50 int DumpPrefix (unsigned char *mem, int len, int base, int baselen)
51 {
52 int retval = 0;
53 int i;
54 printf ("[%s%08x%s]%s", FONT_BRIGHT_BLUE, base, FONT_RESET, FONT_BRIGHT_PURPLE);
55 for (i=0; i < baselen; i++)
56 {
57 if (base+i >= len)
58 {
59 printf (" \?\?");
60 retval = -1;
61 } else {
62 printf (" %02x", mem[base+i]);
63 }
64 }
65 switch (baselen)
66 {
67 case 3: printf ( "%s ", FONT_RESET); break;
68 case 2: printf ( "%s ", FONT_RESET); break;
69 case 1: printf ( "%s ", FONT_RESET); break;
70 case 0: printf ( "%s ", FONT_RESET); break;
71 default: printf ("%s\n ", FONT_RESET); break;
72 }
73 if (retval) { printf ("%sRAN OUT OF DATA%s\n", FONT_BRIGHT_RED, FONT_RESET); }
74 return retval;
75 }
76
DumpInstrument(unsigned char * mem,int len,int base,int instrument)77 int DumpInstrument (unsigned char *mem, int len, int base, int instrument)
78 {
79 uint16_t samplelength;
80 uint16_t loopstart;
81 uint16_t looplength;
82 int i;
83
84 printf ("[%sINSTRUMENT %02d / PCM Sample%s]\n", FONT_BRIGHT_CYAN, instrument + 1, FONT_RESET);
85
86 if (DumpPrefix (mem, len, base + 0x00, 22)) return -1;
87 printf ("Name: \"");
88 for (i=0; i < 22; i++)
89 {
90 if (!mem[base + 0x00 + i])
91 {
92 break;
93 }
94 putchar (mem[base + 0x00 + i]);
95 }
96 printf("\"\n");
97
98 if (DumpPrefix (mem, len, base + 22, 2)) return -1;
99 samplelength = (mem[base+22] << 8) | mem[base+23];
100 printf ("SampleLength: %d\n", (int)samplelength);
101
102 if (DumpPrefix (mem, len, base + 24, 1)) return -1;
103 printf ("FineTuning: %d", (int)(int8_t)((mem[base + 24] & 0x0f)|((mem[base+24]&0x08)?0xf0:0x00)));
104 if (mem[base+24]&0xf0) printf ("%s (WARNING, the upper nibble is not zero)%s", FONT_BRIGHT_YELLOW, FONT_RESET);
105 printf("\n");
106
107 if (DumpPrefix (mem, len, base + 25, 1)) return -1;
108 printf ("Volume: %d", mem[base+25]);
109 if (mem[base+25] > 64)
110 {
111 printf ("%s (WARNING, value out of range)%s", FONT_BRIGHT_YELLOW, FONT_RESET);
112 }
113 printf("\n");
114
115 if (DumpPrefix (mem, len, base + 26, 2)) return -1;
116 loopstart = (mem[base+26] << 8) | mem[base+27];
117 printf ("LoopStart: %d", (int)loopstart);
118 if ((samplelength && (loopstart > samplelength)) && ((!samplelength) && (loopstart > 1)))
119 {
120 printf ("%s (WARNING, value out of range)%s", FONT_BRIGHT_YELLOW, FONT_RESET);
121 }
122 printf ("\n");
123
124 if (DumpPrefix (mem, len, base + 26, 2)) return -1;
125 looplength = (mem[base+26] << 8) | mem[base+27];
126 printf ("LoopLength: %d", (int)looplength);
127 if ((samplelength && ((int)loopstart + looplength > samplelength)) && ((!samplelength) && (looplength > 0)))
128 {
129 printf ("%s (WARNING, value out of range)%s", FONT_BRIGHT_YELLOW, FONT_RESET);
130 }
131 printf ("\n");
132
133 return 0;
134 }
135
136 #if 0
137 void print_note (unsigned char note)
138 {
139 char *text[16] = {"C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#", "B-", "?c", "?d", "?e", "?f"};
140
141 if (note == 0xfe)
142 {
143 printf ("-0-");
144 if (savepatterns)
145 {
146 fprintf (savepatterns, "-0-");
147 }
148 return;
149 }
150 if (note >= 0x60)
151 {
152 printf ("...");
153 if (savepatterns)
154 {
155 fprintf (savepatterns, "...");
156 }
157 return;
158 }
159
160 if ((note & 0x0f) >= 12) printf ("%s", FONT_BRIGHT_RED);
161 printf ("%s", text[note & 0x0f]);
162 if (savepatterns)
163 {
164 fprintf (savepatterns, "%s", text[note & 0x0f]);
165 }
166 if ((note & 0x0f) >= 12) printf ("%s", FONT_RESET);
167
168 printf ("%d", note >> 4);
169 if (savepatterns)
170 {
171 fprintf (savepatterns, "%d", note>>4);
172 }
173 }
174 #endif
175
DumpPattern(unsigned char * mem,int len,int base,int channels)176 int DumpPattern (unsigned char *mem, int len, int base, int channels)
177 {
178 int i;
179
180 for (i=0; i < 64; i++)
181 {
182 int j;
183
184 if (DumpPrefix (mem, len, base, channels * 4)) return -1;
185
186 printf("%02X |", i);
187 if (savepatterns)
188 {
189 fprintf (savepatterns, "%02X | ", i);
190 }
191
192 for (j=0; j < channels; j++)
193 {
194 uint8_t instrument = (mem[base] & 0xf0) | (mem[base+2]>>4);
195 uint16_t period = ((mem[base] & 0x0f) << 8) | mem[base+1];
196 uint8_t effect = mem[base+2] & 0x0f;
197 uint8_t param = mem[base+3];
198 base += 4;
199
200 if (period)
201 {
202 printf (" %03X ", period);
203 } else {
204 printf (" ... ");
205 }
206
207 if (instrument)
208 {
209 printf ("%02X ", instrument);
210 } else {
211 printf (".. ");
212 }
213
214 printf ("%01X%02X |", effect, param);
215
216 if (savepatterns)
217 {
218 if (period)
219 {
220 fprintf (savepatterns, " %03X ", period);
221 } else {
222 fprintf (savepatterns, " ... ");
223 }
224
225 if (instrument)
226 {
227 fprintf (savepatterns, "%02X ", instrument);
228 } else {
229 fprintf (savepatterns, ".. ");
230 }
231
232 fprintf (savepatterns, "%01X%02X |", effect, param);
233 }
234 }
235 printf("\n");
236 if (savepatterns)
237 {
238 fprintf (savepatterns, "\n");
239 }
240 }
241
242 return 0;
243 }
244
DumpPatterns(unsigned char * mem,int len,int ofs,int channels,int patterns)245 int DumpPatterns (unsigned char *mem, int len, int ofs, int channels, int patterns)
246 {
247 int i;
248
249 for (i=0; i < patterns; i++)
250 {
251 printf ("[%sPATTERN %d%s]\n", FONT_BRIGHT_CYAN, i, FONT_RESET);
252 if (savepatterns)
253 {
254 fprintf (savepatterns, "PATTERN %d\n", i);
255 }
256 if (DumpPattern(mem, len, ofs + i * channels * 256, channels)) return -1;
257 }
258
259 return 0;
260 }
261
262 #if 0
263 int DumpHeader (unsigned char *mem, int len)
264 {
265 int i, j;
266
267 if (len < 0x30)
268 {
269 fprintf (stderr, "%sERROR: len < sizeof(FileHeader)%s\n", FONT_BRIGHT_RED, FONT_RESET);
270 return 1;
271 }
272
273 printf ("[%sHEADER%s]\n", FONT_BRIGHT_CYAN, FONT_RESET);
274
275 /* hdr.name */
276 DumpPrefix (mem, len, 0x00, 20);
277 printf ("Name: \"");
278 for (i=0; i < 20; i++)
279 {
280 if (!mem[0x00+i])
281 break;
282 printf ("%c", (char)mem[0x00+i]);
283 }
284 printf ("\"\n");
285
286 DumpPrefix (mem, len, 0x14, 8);
287 printf ("Tracker: \"");
288 j=0;
289 for (i=0; i < 8; i++)
290 {
291 if ((mem[0x14+i] < 0x20) || (mem[0x14+i] >= 0x80))
292 {
293 j = 1;
294 }
295 }
296 for (i=0; i < 8; i++)
297 {
298 if (!mem[0x14+i])
299 break;
300 printf ("%c", (char)mem[0x14+i]);
301 }
302 printf ("\" %s%s%s\n",
303 j ? FONT_BRIGHT_RED : FONT_BRIGHT_GREEN,
304 j ? "Non-ASCII" : "OK",
305 FONT_RESET);
306
307 DumpPrefix (mem, len, 0x1c, 1);
308 printf ("Signature: %s%s%s\n",
309 (mem[0x1c] == 0x1A) ? FONT_BRIGHT_GREEN : (mem[0x1c] == 0x02) ? FONT_BRIGHT_YELLOW : FONT_BRIGHT_RED,
310 (mem[0x1c] == 0x1A) ? "OK" : (mem[0x1c] == 0x02) ? "Known invalid value" : "Failed!!!!",
311 FONT_RESET);
312
313 DumpPrefix (mem, len, 0x1d, 1);
314 printf ("Type: ");
315 switch (mem[0x1d])
316 {
317 case 1: printf ("STM song w/o samples\n"); break;
318 case 2: printf ("STM module\n"); break;
319 case 16: printf ("S3M module, FAILED !!!!!\n"); return 1;
320 default: printf ("Unknown, FAILED !!!!!\n"); return 1;
321 }
322
323 DumpPrefix (mem, len, 0x1e, 2);
324 printf ("Version: %d.%d\n", mem[0x1e], mem[0x1f]);
325
326 DumpPrefix (mem, len, 0x20, 1);
327 printf ("Initial Tempo: %d\n", mem[0x20]);
328
329 DumpPrefix (mem, len, 0x21, 1);
330 printf ("Patterns: %d\n", mem[0x21]);
331
332 DumpPrefix (mem, len, 0x22, 1);
333 printf ("Global Volume: %d\n", mem[0x22]);
334
335 DumpPrefix (mem, len, 0x23, 13);
336 printf ("(Reserved/not used)\n");
337
338 return 0;
339 }
340
341 #endif
342
DumpOrders(unsigned char * mem,int len,int ofs,int count)343 int DumpOrders (unsigned char *mem, int len, int ofs, int count)
344 {
345 int MaxOrder = 0;
346 int i;
347
348 printf ("[%sORDERS%s]\n", FONT_BRIGHT_CYAN, FONT_RESET);
349
350 if (DumpPrefix (mem, len, ofs, count)) return -1;
351
352 for (i=0; i < count; i++)
353 {
354 printf ("%d ", mem[ofs+i]);
355 if (mem[ofs+i] > MaxOrder)
356 {
357 MaxOrder = mem[ofs+i];
358 }
359 }
360 printf ("\n");
361 if (count < 128)
362 {
363 if (DumpPrefix (mem, len, ofs + count, 128-count)) return -1;
364 printf("(");
365 for (i=count; i < 128; i++)
366 {
367 printf ("%d%s", mem[ofs+i], (i!=127)?" ":"");
368 if (mem[ofs+i] > MaxOrder)
369 {
370 MaxOrder = mem[ofs+i];
371 }
372 }
373 printf (")\n");
374 }
375
376 return MaxOrder;
377 }
378
379 #if 0
380
381 int ParseSTM (unsigned char *mem, int len)
382 {
383 int i;
384 int patternlen = 0;
385
386 if (DumpHeader (mem, len))
387 {
388 return -1;
389 }
390
391 for (i=0; i < 31; i++)
392 {
393 if (DumpInstrument (mem, len, 0x30 + i*0x20, i))
394 {
395 return -1;
396 }
397 }
398
399 if (DumpOrders (mem, len, mem[0x1f]?128:64, mem[0x21]))
400 {
401 return -1;
402 }
403
404 for (i=0; i < mem[0x21]; i++)
405 {
406 int retval = DumpPattern (mem, len, 0x30 + 0x20*31 + (mem[0x1f]?128:64) + patternlen, i);
407 if (retval < 0)
408 {
409 return -1;
410 }
411 patternlen += DumpPattern (mem, len, 0x30 + 0x20*31 + (mem[0x1f]?128:64) + patternlen, i);
412 }
413 if (savepatterns)
414 {
415 fclose (savepatterns);
416 }
417
418 for (i=0; i < 31; i++)
419 {
420 if (Instruments[i].length > 0)
421 {
422 printf ("[%sINSTRUMENT %02x SAMPLE DATA%s]\n", FONT_BRIGHT_CYAN, i + 1, FONT_RESET);
423
424 printf ("[%s%08x-%08x%s]%s\n", FONT_BRIGHT_BLUE, Instruments[i].offset, Instruments[i].offset + Instruments[i].length - 1, FONT_RESET, FONT_RESET);
425 if (savesamples)
426 {
427 if ((Instruments[i].offset + Instruments[i].length) > len)
428 {
429 printf ("%sWARNING: Unable to store instrument %d, missing data\n%s", FONT_BRIGHT_YELLOW, i + 1, FONT_RESET);
430 } else {
431 char filename[33];
432 int fd;
433 snprintf (filename, sizeof (filename), "Instrument %02d.signed 8bit.sample", i+1);
434 fd = open (filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
435 if (fd < 0)
436 {
437 printf ("%sWARNING: Unable to open %s%s\n", FONT_BRIGHT_YELLOW, filename, FONT_RESET);
438 } else {
439 write (fd, mem + Instruments[i].offset, Instruments[i].length);
440 close (fd);
441 printf ("Saved %s\n", filename);
442 }
443 }
444 }
445 }
446 }
447
448 return 0;
449 }
450
451 #endif
452
ParseMOD(unsigned char * mem,int len,int instruments,int channels,int signature)453 int ParseMOD (unsigned char *mem, int len, int instruments, int channels, int signature)
454 {
455 int i, MaxOrder;
456 uint8_t NoOrders;
457 int ofs = 0;
458
459 if (DumpPrefix (mem, len, 0, 20)) return -1;
460 printf ("Name: \"");
461 for (i=0; i < 20; i++)
462 {
463 if (!mem[0x00+i])
464 break;
465 printf ("%c", (char)mem[0x00+i]);
466 }
467 ofs = 20;
468 printf ("\"\n");
469
470 for (i=0; i < instruments; i++)
471 {
472 if (DumpInstrument(mem, len, ofs, i)) return -1;
473 ofs += 30;
474 }
475
476 if (DumpPrefix (mem, len, ofs, 1)) return -1;
477 NoOrders = mem[ofs++];
478 if ((NoOrders < 1) || (NoOrders > 128))
479 {
480 printf ("Number of orders: %d %s(OUT OF RANGE)%s\n", (int)NoOrders, FONT_BRIGHT_RED, FONT_RESET);
481 } else {
482 printf ("Number of orders: %d\n", (int)NoOrders);
483 }
484
485 if (DumpPrefix (mem, len, ofs, 1)) return -1;
486 printf ("(Restart position: %d)\n", (int)mem[ofs++]);
487
488 MaxOrder = DumpOrders(mem, len, ofs, NoOrders);
489 if (MaxOrder < 0) return -1;
490 ofs += 128;
491
492 if (signature)
493 {
494 if (DumpPrefix (mem, len, ofs, 4)) return -1;
495 printf ("Signtaure: \"%c%c%c%c\"\n", mem[ofs+0], mem[ofs+1], mem[ofs+2], mem[ofs+3]);
496 ofs+=4;
497 }
498
499 if (DumpPatterns(mem, len, ofs, channels, MaxOrder + 1)) return -1;
500
501 ofs += channels * 256;
502
503 #if 0
504 if (DumpSamples(mem, len, ofs, instruments)) return -1;
505 #endif
506
507 return 0;
508 }
509
preParseMOD15(unsigned char * mem,int len,int * channels15instruments)510 int preParseMOD15 (unsigned char *mem, int len, int *channels15instruments)
511 {
512 int i;
513 uint32_t samplelengths15 = 0;
514 int canbe15instruments = 1;
515 uint8_t highestorder = 0;
516
517 if (len < (20 + 15*30))
518 {
519 printf ("%sERROR: no space for even 15 instruments, the minimum%s\n", FONT_BRIGHT_RED, FONT_RESET);
520 return -2;
521 }
522
523 for (i=0; i < 15; i++)
524 {
525 uint16_t samplelength = (mem[20+22+i*30] << 8) | mem[20+23+i*30];
526 uint8_t finetune = mem[20+24+i*30];
527 uint8_t volume = mem[20+25+i*30];
528 uint16_t repeatstart = (mem[20+26+i*30] << 8) | mem[20+27+i*30];
529 uint16_t repeatlen = (mem[20+28+i*30] << 8) | mem[20+29+i*30];
530
531 if (finetune & 0xf0)
532 {
533 printf ("%sWARNING: instrument %d have high nibble in finetuning set%s\n", FONT_BRIGHT_YELLOW, i + 1, FONT_RESET);
534 }
535 if (volume > 64)
536 {
537 printf ("%sERROR: instrument %d volume is out of range%s\n", FONT_BRIGHT_RED, i + 1, FONT_RESET);
538 return -2;
539 }
540 if (samplelength <= 1)
541 {
542 if (repeatlen > 1)
543 {
544 printf ("%sERROR: instrument %d looplen is out of range for empty instrument%s\n", FONT_BRIGHT_RED, i + 1, FONT_RESET);
545 return -2;
546 }
547 } else {
548 if (repeatstart >= samplelength)
549 {
550 printf ("%sERROR: instrument %d loopstart is out of range%s\n", FONT_BRIGHT_RED, i + 1, FONT_RESET);
551 return -2;
552 }
553 if (repeatlen > samplelength)
554 {
555 printf ("%sERROR: instrument %d looplen is out of range%s\n", FONT_BRIGHT_RED, i + 1, FONT_RESET);
556 return -2;
557 }
558 if (((uint32_t)repeatstart + repeatlen) > samplelength)
559 {
560 printf ("%sERROR: instrument %d loopstart + looplen is out of range%s\n", FONT_BRIGHT_RED, i + 1, FONT_RESET);
561 return -2;
562 }
563 samplelengths15 += samplelength;
564 }
565 //printf ("15.Instrument: len=%04x loopstart=%04x looplen=%04x volume=%02x finetune=%d\n", samplelength, repeatstart, repeatlen, volume, finetune);
566 }
567
568
569 if (len < (20 + 15*30 + 130))
570 {
571 printf ("%sERROR: No room for order data - can not be 15 instrument format%s\n", FONT_BRIGHT_RED, FONT_RESET);
572 return -2;
573 }
574
575 if ((mem[20+15*30] < 1) || (mem[20+15*30] > 128))
576 {
577 printf ("%sWARNING: Order length (%d) is out of range - can not be 15 instrument format%s\n", FONT_BRIGHT_YELLOW, mem[20+22+15*30], FONT_RESET);
578 return -1;
579 }
580
581 for (i=0; i < 128; i++)
582 {
583 if (mem[20+15*30+2 + i] > highestorder)
584 {
585 highestorder = mem[20+15*30+2 + i];
586 }
587 }
588 if (highestorder >= 64)
589 {
590 printf ("%sWARNING: Order > 63 not possible in 15 instrument format - can not be 15 instrument file%s\n", FONT_BRIGHT_YELLOW, FONT_RESET);
591 return -1;
592 }
593
594 if ((20+15*30+2+128+4 + (highestorder+1)*1024) > len)
595 {
596 printf ("%sERROR: Not enough space for pattern data - can not be a 15 instrument file%s\n", FONT_BRIGHT_RED, FONT_RESET);
597 return -1;
598 }
599
600 if ((20+15*30+2+128+4 + (highestorder+1)*1024 + (samplelengths15<<1)) > len)
601 {
602 printf ("%sERROR: Not enough space for sample data - can not be a 15 instrument file%s\n", FONT_BRIGHT_RED, FONT_RESET);
603 return -1;
604 }
605
606 if ((20+15*30+2+128+4 + (highestorder+1)*1024 + (samplelengths15<<1)) != len)
607 {
608 printf ("%sWARNING: Got %d bytes extra data for 15 instrument file%s\n", FONT_BRIGHT_YELLOW, len - (20+15*30+2+128+4 + (highestorder+1)*1024 + (samplelengths15<<1)), FONT_RESET);
609 }
610
611 return canbe15instruments;
612 }
613
preParseMOD31(unsigned char * mem,int len,int * channels31instruments)614 int preParseMOD31 (unsigned char *mem, int len, int *channels31instruments)
615 {
616 int i;
617 uint32_t samplelengths31 = 0;
618 int canbe31instruments = 0;
619 uint8_t highestorder = 0;
620
621 if (len < (20 + 31*30 + 130 + 4))
622 {
623 printf ("%sERROR: no space for even 31 instruments, the minimum%s\n", FONT_BRIGHT_RED, FONT_RESET);
624 return -1;
625 }
626
627 for (i=0; i < 31; i++)
628 {
629 uint16_t samplelength = (mem[20+22+i*30] << 8) | mem[20+23+i*30];
630 uint8_t finetune = mem[20+24+i*30];
631 uint8_t volume = mem[20+25+i*30];
632 uint16_t repeatstart = (mem[20+26+i*30] << 8) | mem[20+27+i*30];
633 uint16_t repeatlen = (mem[20+28+i*30] << 8) | mem[20+29+i*30];
634
635 if (finetune & 0xf0)
636 {
637 printf ("%sWARNING: instrument %d have high nibble in finetuning set%s\n", FONT_BRIGHT_YELLOW, i + 1, FONT_RESET);
638 }
639 if (volume > 64)
640 {
641 printf ("%sWARNING: instrument %d volume is out of range - can not be 31 instrument file%s\n", FONT_BRIGHT_YELLOW, i + 1, FONT_RESET);
642 return -1;
643 }
644 if (samplelength <= 1)
645 {
646 if (repeatlen > 1)
647 {
648 printf ("%sWARNING: instrument %d looplen is out of range for empty instrument - can not be 31 instrument file%s\n", FONT_BRIGHT_YELLOW, i + 1, FONT_RESET);
649 return -1;
650 }
651 } else {
652 if (repeatstart >= samplelength)
653 {
654 printf ("%sWARNING: instrument %d loopstart is out of range - can not be 31 instrument file%s\n", FONT_BRIGHT_YELLOW, i + 1, FONT_RESET);
655 return -1;
656 }
657 if (repeatlen > samplelength)
658 {
659 printf ("%sWARNING: instrument %d looplen is out of range - can not be 31 instrument file%s\n", FONT_BRIGHT_YELLOW, i + 1, FONT_RESET);
660 return -1;
661 }
662 if (((uint32_t)repeatstart + repeatlen) > samplelength)
663 {
664 printf ("%sWARNING: instrument %d loopstart + looplen is out of range - can not be 31 instrument file%s\n", FONT_BRIGHT_YELLOW, i + 1, FONT_RESET);
665 return -1;
666 }
667 samplelengths31 += samplelength;
668 }
669 //printf ("31.Instrument: len=%04x loopstart=%04x looplen=%04x volume=%02x finetune=%d\n", samplelength, repeatstart, repeatlen, volume, finetune);
670 }
671
672 if ((mem[20+31*30] < 1) || (mem[20+31*30] > 128))
673 {
674 printf ("%sWARNING: Order length (%d) is out of range - can not be 31 instrument format%s\n", FONT_BRIGHT_YELLOW, mem[20+31*30], FONT_RESET);
675
676 return -1;
677 }
678 for (i=0; i < 128; i++)
679 {
680 if (mem[20+31*30+2 + i] > highestorder)
681 {
682 highestorder = mem[20+31*30+2 + i];
683 }
684 }
685
686 if (!memcmp(&mem[20+31*30+2+128], "M.K.", 4))
687 {
688 printf ("%sNOTE: got M.K. signature in 31 instrument format%s\n", FONT_BRIGHT_GREEN, FONT_RESET);
689 canbe31instruments = 1;
690 if (highestorder >= 64)
691 {
692 printf ("%sWARNING: Order > 63 not possible in M.K. format - can not be 31 instrument file%s\n", FONT_BRIGHT_YELLOW, FONT_RESET);
693 return -1;
694 }
695 } else if (!memcmp(&mem[20+31*30+2+128], "M!K!", 4))
696 {
697 printf ("%sNOTE: got M!K! signature in 31 instrument format%s\n", FONT_BRIGHT_GREEN, FONT_RESET);
698 canbe31instruments = 1;
699 if (highestorder < 64)
700 {
701 printf ("%sWARNING: Order < 64 not possible in M!K! format - can not be 31 instrument file%s\n", FONT_BRIGHT_YELLOW, FONT_RESET);
702 return -1;
703 }
704 } else if (!memcmp(&mem[20+31*30+2+128], "FLT4", 4)) { printf ("%sNOTE: got FLT4 - probably StarTrekker 4-channel MOD%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 4;
705 } else if (!memcmp(&mem[20+31*30+2+128], "FLT8", 4)) { printf ("%sNOTE: got FLT8 - probably StarTrekker 8-channel MOD%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 8;
706 } else if (!memcmp(&mem[20+31*30+2+128], "CD81", 4)) { printf ("%sNOTE: got CD81 - probably Oktalyzer for Atari ST?%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 8;
707 } else if (!memcmp(&mem[20+31*30+2+128], "OKTA", 4)) { printf ("%sNOTE: got OKTA - probably Oktalyzer for Atari ST?%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 8;
708 } else if (!memcmp(&mem[20+31*30+2+128], "OCTA", 4)) { printf ("%sNOTE: got OKTA - probably OctaMED%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 8;
709
710 } else if (!memcmp(&mem[20+31*30+2+128], "1TDZ", 4)) { printf ("%sNOTE: got 1TDZ - TakeTracker extension for 1 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 1;
711 } else if (!memcmp(&mem[20+31*30+2+128], "2TDZ", 4)) { printf ("%sNOTE: got 2TDZ - TakeTracker extension for 3 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 2;
712 } else if (!memcmp(&mem[20+31*30+2+128], "3TDZ", 4)) { printf ("%sNOTE: got 3TDZ - TakeTracker extension for 3 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 3;
713 } else if (!memcmp(&mem[20+31*30+2+128], "5CHN", 4)) { printf ("%sNOTE: got 5CHN - TakeTracker extension for 5 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 5;
714 } else if (!memcmp(&mem[20+31*30+2+128], "7CHN", 4)) { printf ("%sNOTE: got 7CHN - TakeTracker extension for 7 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 7;
715 } else if (!memcmp(&mem[20+31*30+2+128], "9CHN", 4)) { printf ("%sNOTE: got 9CHN - TakeTracker extension for 9 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 9;
716 } else if (!memcmp(&mem[20+31*30+2+128], "10CN", 4)) { printf ("%sNOTE: got 10CN - TakeTracker extension for 10 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 10;
717 } else if (!memcmp(&mem[20+31*30+2+128], "11CN", 4)) { printf ("%sNOTE: got 11CN - TakeTracker extension for 11 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 11;
718 } else if (!memcmp(&mem[20+31*30+2+128], "12CN", 4)) { printf ("%sNOTE: got 12CN - TakeTracker extension for 12 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 12;
719 } else if (!memcmp(&mem[20+31*30+2+128], "13CN", 4)) { printf ("%sNOTE: got 13CN - TakeTracker extension for 13 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 13;
720 } else if (!memcmp(&mem[20+31*30+2+128], "14CN", 4)) { printf ("%sNOTE: got 14CN - TakeTracker extension for 14 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 14;
721 } else if (!memcmp(&mem[20+31*30+2+128], "15CN", 4)) { printf ("%sNOTE: got 15CN - TakeTracker extension for 15 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 15;
722 } else if (!memcmp(&mem[20+31*30+2+128], "16CN", 4)) { printf ("%sNOTE: got 16CN - TakeTracker extension for 16 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 16;
723 } else if (!memcmp(&mem[20+31*30+2+128], "17CN", 4)) { printf ("%sNOTE: got 17CN - TakeTracker extension for 17 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 17;
724 } else if (!memcmp(&mem[20+31*30+2+128], "18CN", 4)) { printf ("%sNOTE: got 18CN - TakeTracker extension for 18 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 18;
725 } else if (!memcmp(&mem[20+31*30+2+128], "19CN", 4)) { printf ("%sNOTE: got 19CN - TakeTracker extension for 19 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 19;
726 } else if (!memcmp(&mem[20+31*30+2+128], "20CN", 4)) { printf ("%sNOTE: got 20CN - TakeTracker extension for 20 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 20;
727 } else if (!memcmp(&mem[20+31*30+2+128], "21CN", 4)) { printf ("%sNOTE: got 21CN - TakeTracker extension for 21 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 21;
728 } else if (!memcmp(&mem[20+31*30+2+128], "22CN", 4)) { printf ("%sNOTE: got 22CN - TakeTracker extension for 22 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 22;
729 } else if (!memcmp(&mem[20+31*30+2+128], "23CN", 4)) { printf ("%sNOTE: got 23CN - TakeTracker extension for 23 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 23;
730 } else if (!memcmp(&mem[20+31*30+2+128], "24CN", 4)) { printf ("%sNOTE: got 24CN - TakeTracker extension for 24 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 24;
731 } else if (!memcmp(&mem[20+31*30+2+128], "25CN", 4)) { printf ("%sNOTE: got 25CN - TakeTracker extension for 25 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 25;
732 } else if (!memcmp(&mem[20+31*30+2+128], "26CN", 4)) { printf ("%sNOTE: got 26CN - TakeTracker extension for 26 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 26;
733 } else if (!memcmp(&mem[20+31*30+2+128], "27CN", 4)) { printf ("%sNOTE: got 27CN - TakeTracker extension for 27 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 27;
734 } else if (!memcmp(&mem[20+31*30+2+128], "28CN", 4)) { printf ("%sNOTE: got 28CN - TakeTracker extension for 28 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 28;
735 } else if (!memcmp(&mem[20+31*30+2+128], "29CN", 4)) { printf ("%sNOTE: got 29CN - TakeTracker extension for 29 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 29;
736 } else if (!memcmp(&mem[20+31*30+2+128], "30CN", 4)) { printf ("%sNOTE: got 30CN - TakeTracker extension for 30 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 30;
737 } else if (!memcmp(&mem[20+31*30+2+128], "31CN", 4)) { printf ("%sNOTE: got 31CN - TakeTracker extension for 31 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 31;
738 } else if (!memcmp(&mem[20+31*30+2+128], "33CN", 4)) { printf ("%sNOTE: got 32CN - TakeTracker extension for 32 channel%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 32;
739
740 } else if (!memcmp(&mem[20+31*30+2+128], "2CHN", 4)) { printf ("%sNOTE: got 2CHN - uncommon 2 channel format%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 2;
741 } else if (!memcmp(&mem[20+31*30+2+128], "6CHN", 4)) { printf ("%sNOTE: got 6CHN - common 6 channel format%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 6;
742 } else if (!memcmp(&mem[20+31*30+2+128], "8CHN", 4)) { printf ("%sNOTE: got 8CHN - common 8 channel format%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 8;
743 } else if (!memcmp(&mem[20+31*30+2+128], "10CH", 4)) { printf ("%sNOTE: got 10CH - common 10 channel format%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 10;
744 } else if (!memcmp(&mem[20+31*30+2+128], "12CH", 4)) { printf ("%sNOTE: got 12CH - common 10 channel format%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 12;
745 } else if (!memcmp(&mem[20+31*30+2+128], "14CH", 4)) { printf ("%sNOTE: got 14CH - common 10 channel format%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 14;
746 } else if (!memcmp(&mem[20+31*30+2+128], "16CH", 4)) { printf ("%sNOTE: got 16CH - common 10 channel format%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 16;
747 } else if (!memcmp(&mem[20+31*30+2+128], "18CH", 4)) { printf ("%sNOTE: got 18CH - common 10 channel format%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 18;
748 } else if (!memcmp(&mem[20+31*30+2+128], "20CH", 4)) { printf ("%sNOTE: got 20CH - common 10 channel format%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 20;
749 } else if (!memcmp(&mem[20+31*30+2+128], "22CH", 4)) { printf ("%sNOTE: got 22CH - common 10 channel format%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 22;
750 } else if (!memcmp(&mem[20+31*30+2+128], "24CH", 4)) { printf ("%sNOTE: got 24CH - common 10 channel format%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 24;
751 } else if (!memcmp(&mem[20+31*30+2+128], "26CH", 4)) { printf ("%sNOTE: got 26CH - common 10 channel format%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 26;
752 } else if (!memcmp(&mem[20+31*30+2+128], "28CH", 4)) { printf ("%sNOTE: got 28CH - common 10 channel format%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 28;
753 } else if (!memcmp(&mem[20+31*30+2+128], "30CH", 4)) { printf ("%sNOTE: got 30CH - common 10 channel format%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 30;
754 } else if (!memcmp(&mem[20+31*30+2+128], "32CH", 4)) { printf ("%sNOTE: got 32CH - common 10 channel format%s\n", FONT_BRIGHT_GREEN, FONT_RESET); canbe31instruments = (highestorder < 64); *channels31instruments = 32;
755 } else {
756 if (
757 (((mem[20+31*30+2+128] >= 'A') && (mem[20+31*30+2+128] <= 'Z')) ||
758 ((mem[20+31*30+2+128] >= '0') && (mem[20+31*30+2+128] <= '9')) ||
759 (mem[20+31*30+2+128] == '.') ||
760 (mem[20+31*30+2+128] == '!') ||
761 (mem[20+31*30+2+128] == '#')) &&
762 (((mem[20+31*30+2+129] >= 'A') && (mem[20+31*30+2+129] <= 'Z')) ||
763 ((mem[20+31*30+2+129] >= '0') && (mem[20+31*30+2+129] <= '9')) ||
764 (mem[20+31*30+2+129] == '.') ||
765 (mem[20+31*30+2+129] == '!') ||
766 (mem[20+31*30+2+129] == '#')) &&
767 (((mem[20+31*30+2+130] >= 'A') && (mem[20+31*30+2+130] <= 'Z')) ||
768 ((mem[20+31*30+2+130] >= '0') && (mem[20+31*30+2+130] <= '9')) ||
769 (mem[20+31*30+2+130] == '.') ||
770 (mem[20+31*30+2+130] == '!') ||
771 (mem[20+31*30+2+130] == '#')) &&
772 (((mem[20+31*30+2+131] >= 'A') && (mem[20+31*30+2+131] <= 'Z')) ||
773 ((mem[20+31*30+2+131] >= '0') && (mem[20+31*30+2+131] <= '9')) ||
774 (mem[20+31*30+2+131] == '.') ||
775 (mem[20+31*30+2+131] == '!') ||
776 (mem[20+31*30+2+131] == '#')))
777 {
778 printf ("%sWARNING: Unknown TAG: \"%c%c%c%c\"%s\n", FONT_BRIGHT_YELLOW, mem[20+31*30+2+128], mem[20+31*30+2+129], mem[20+31*30+2+130], mem[20+31*30+2+131], FONT_RESET);
779 *channels31instruments = 4;
780 canbe31instruments = 0;
781 } else {
782 printf ("%sERROR: Illegal TAG - can not be a 31 instrument file%s\n", FONT_BRIGHT_RED, FONT_RESET);
783 }
784 }
785
786 if ((20+31*30+2+128+4+ (highestorder+1)*1024) > len)
787 {
788 printf ("%sERROR: Not enough space for pattern data - can not be a 31 instrument file%s\n", FONT_BRIGHT_RED, FONT_RESET);
789 return -1;
790 }
791
792 if ((20+31*30+2+128+4 + (highestorder+1)*1024 + (samplelengths31<<1)) > len)
793 {
794 printf ("%sERROR: Not enough space for sample data - can not be a 31 instrument file%s\n", FONT_BRIGHT_RED, FONT_RESET);
795 return -1;
796 }
797
798 if ((20+31*30+2+128+4 + (highestorder+1)*1024 + (samplelengths31<<1)) != len)
799 {
800 printf ("%sWARNING: Got %d bytes extra data for 31 instrument file%s\n", FONT_BRIGHT_YELLOW, len - (20+31*30+2+128+4 + (highestorder+1)*1024 + (samplelengths31<<1)), FONT_RESET);
801 }
802
803 return canbe31instruments;
804 }
805
806
preParseMOD(unsigned char * mem,int len,int * instruments,int * channels,int * signature)807 int preParseMOD (unsigned char *mem, int len, int *instruments, int *channels, int *signature)
808 {
809 int i;
810
811 int channels15instruments = 4;
812 int channels31instruments = 4;
813 int canbe15instruments;
814 int canbe31instruments;
815
816 if (len < 20)
817 {
818 printf ("%sERROR: no space for title%s\n", FONT_BRIGHT_RED, FONT_RESET);
819 return -1;
820 }
821 do
822 {
823 int invalid = 0;
824 int upper = 0;
825 int lower = 0;
826 int other = 0;
827 int hi = 0;
828 for (i=0; i < 20; i++)
829 {
830 if (mem[i] == 0)
831 {
832 break;
833 }
834 if ((mem[i] < 0x20) || ((mem[i] >= 0x7f) && (mem[i] <= 0x9f)))
835 {
836 invalid++;
837 } else if ((mem[i] >= 'A') && (mem[i] <= 'Z'))
838 {
839 upper++;
840 } else if ((mem[i] >= 'a') && (mem[i] <= 'z'))
841 {
842 lower++;
843 } else if (!(mem[i] & 0x80))
844 {
845 other++;
846 } else {
847 hi++;
848 }
849 }
850 if (invalid)
851 {
852 printf ("Title: contains invalid characters\n");
853 } else if (hi || lower)
854 {
855 printf ("Title: Can not be \"Original Protracker\"\n");
856 } else if (lower)
857 {
858 printf ("Title: Might be \"Original Protracker\"\n");
859 }
860 } while (0);
861
862 canbe15instruments = preParseMOD15 (mem, len, &channels15instruments);
863 if (canbe15instruments < -1)
864 {
865 return -1;
866 }
867 canbe31instruments = preParseMOD31 (mem, len, &channels31instruments);
868
869 if (canbe31instruments>0)
870 {
871 printf ("%sINFO: File is 31 instruments, %d channels%s\n", FONT_BRIGHT_GREEN, channels31instruments, FONT_RESET);
872 *instruments = 31; *channels = channels31instruments; *signature = 1;
873 return 0;
874 }
875 if (canbe15instruments>0)
876 {
877 printf ("%sINFO: File is 15 instruments, %d channels%s\n", FONT_BRIGHT_GREEN, channels15instruments, FONT_RESET);
878 *instruments = 15; *channels = channels15instruments; *signature = 0;
879 return 0;
880 }
881 if (canbe31instruments==0)
882 {
883 printf ("%sINFO: File is probably 31 instruments, %d channels%s\n", FONT_BRIGHT_GREEN, channels31instruments, FONT_RESET);
884 *instruments = 31; *channels = channels31instruments; *signature = 1;
885 return 0;
886 }
887 if (canbe15instruments==0)
888 {
889 printf ("%sINFO: File is probably 15 instruments, %d channels%s\n", FONT_BRIGHT_GREEN, channels15instruments, FONT_RESET);
890 *instruments = 15; *channels = channels15instruments; *signature = 0;
891 return 0;
892 }
893
894 return -1;
895 }
896
897 #warning TODO N.T. files!
898
main(int argc,char * argv[])899 int main(int argc, char *argv[])
900 {
901 struct stat st;
902 size_t ps = sysconf(_SC_PAGE_SIZE);
903 int fd;
904 size_t data_mmaped_len;
905 unsigned char *data;
906 int c;
907 char *color = "auto";
908 int help = 0;
909
910 int instruments = 31;
911 int channels = 4;
912 int signature = 1;
913
914 while (1)
915 {
916 int option_index = 0;
917 static struct option long_options[] =
918 {
919 {"color", optional_argument, 0, 0},
920 {"help", no_argument, 0, 'h'},
921 {"savepatterns", no_argument, 0, 'p'},
922 {"savesamples", no_argument, 0, 's'},
923 {0, 0, 0, 0}
924 };
925
926 c = getopt_long(argc, argv, "hsp", long_options, &option_index);
927 if (c == -1)
928 break;
929
930 switch (c)
931 {
932 case 0:
933 if (option_index == 0)
934 {
935 color = optarg;
936 }
937 break;
938 case 'p':
939 if (!savepatterns)
940 {
941 savepatterns = fopen ("patterns.txt", "w");
942 if (!savepatterns)
943 {
944 fprintf (stderr, "Unable to open patterns.txt for writing: %s\n", strerror (errno));
945 return 1;
946 }
947 }
948 break;
949 case 's':
950 savesamples = 1;
951 break;
952 case 'h':
953 help = 1;
954 break;
955 case '?':
956 help = 3;
957 break;
958 default:
959 printf("?? getopt returned character code 0%o ??\n", c);
960 }
961 }
962
963 if (optind != (argc-1))
964 {
965 help = 4;
966 }
967
968 if (!color)
969 {
970 usecolor = 1;
971 } else if (!strcmp (color, "auto"))
972 {
973 usecolor = isatty ( 1 );
974 } else if ((strcmp (color, "never")) && (strcmp (color, "no")))
975 {
976 usecolor = 1;
977 } else {
978 usecolor = 0;
979 }
980
981 if (help)
982 {
983 fprintf (stderr, "Usage:\n%s [--color=auto/never/on] [--savesamples -s] [--savepatterns -p] [--help] file.stm (%d)\n", argv[0], help);
984 return 1;
985 }
986
987 fd = open (argv[optind], O_RDONLY);
988 if (fd < 0)
989 {
990 perror ("open()");
991 return 0;
992 }
993 if (fstat(fd, &st))
994 {
995 perror("fstat()");
996 close (fd);
997 return 0;
998 }
999 if (!st.st_size)
1000 {
1001 fprintf (stderr, "Zero-size file\n");
1002 close (fd);
1003 return 0;
1004 }
1005
1006 // s.data_len = st.st_size;
1007 data_mmaped_len = roundup (st.st_size, ps);
1008 data = mmap (0, data_mmaped_len, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0);
1009
1010 if (data == MAP_FAILED)
1011 {
1012 perror ("mmap() failed");
1013 close (fd);
1014 return 0;
1015 }
1016
1017 if (usecolor)
1018 {
1019 FONT_RESET = "\033[0m";
1020 FONT_BRIGHT_BLACK = "\033[30;1m";
1021 FONT_BRIGHT_RED = "\033[31;1m";
1022 FONT_BRIGHT_GREEN = "\033[32;1m";
1023 FONT_BRIGHT_YELLOW = "\033[33;1m";
1024 FONT_BRIGHT_BLUE = "\033[34;1m";
1025 FONT_BRIGHT_PURPLE = "\033[35;1m";
1026 FONT_BRIGHT_CYAN = "\033[36;1m";
1027 }
1028
1029 if (preParseMOD (data, st.st_size, &instruments, &channels, &signature))
1030 {
1031 goto failed;
1032 }
1033 ParseMOD (data, st.st_size, instruments, channels, signature);
1034
1035 failed:
1036 munmap (data, data_mmaped_len);
1037 close (fd);
1038 return 0;
1039 }
1040