mirror of
https://github.com/Fledge68/WiiFlow_Lite.git
synced 2024-12-26 11:51:56 +01:00
601 lines
16 KiB
C
601 lines
16 KiB
C
/*
|
|
* Copyright (c) 2002, 2003, 2004, 2005, 2007 by Christian Nowak <chnowak@web.de>
|
|
* Last update: 20th October, 2007
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "effects.h"
|
|
#include "modplay.h"
|
|
#include "mod.h"
|
|
|
|
|
|
#define FORMAT_ID 1
|
|
#define DESCRIPTION "Amiga Pro/Soundtracker"
|
|
#define AUTHOR "Christian Nowak <chnowak@web.de>"
|
|
#define VERSION "v0.03b"
|
|
#define COPYRIGHT "Copyright (c) 2002, 2003, 2007"
|
|
|
|
|
|
#define SAFE_MALLOC(dest, a) \
|
|
dest = malloc(a); \
|
|
if (dest == NULL) { \
|
|
MODFILE_Free(mod); \
|
|
return -2; \
|
|
}
|
|
|
|
|
|
|
|
static u32 s3m_finetunes[16] = {
|
|
|
|
7895,7941,7985,8046,8107,8169,8232,8280,
|
|
8363,8413,8463,8529,8581,8651,8723,8757
|
|
};
|
|
|
|
|
|
|
|
#define NUM_AMIGA_FREQS ((22 * 5) + 5)
|
|
static const struct {
|
|
|
|
u16 amigafreq;
|
|
u8 st3note;
|
|
} s3m_amiga2st3[] = {
|
|
{ 0x1ac0, 0x00 }, { 0x1940, 0x01 }, { 0x17d0, 0x02 }, { 0x1680, 0x03 }, { 0x1530, 0x04 },
|
|
{ 0x1400, 0x05 }, { 0x12e0, 0x06 }, { 0x11d0, 0x07 }, { 0x10d0, 0x08 }, { 0x0fe0, 0x09 },
|
|
{ 0x0f00, 0x0a }, { 0x0e2c, 0x0b }, { 0x0d60, 0x10 }, { 0x0ca0, 0x11 }, { 0x0be8, 0x12 },
|
|
{ 0x0b40, 0x13 }, { 0x0a98, 0x14 }, { 0x0a00, 0x15 }, { 0x0970, 0x16 }, { 0x08e8, 0x17 },
|
|
{ 0x0868, 0x18 }, { 0x07f0, 0x19 }, { 0x0780, 0x1a }, { 0x0716, 0x1b }, { 0x06b0, 0x20 },
|
|
{ 0x0650, 0x21 }, { 0x05f5, 0x22 }, { 0x05a0, 0x23 }, { 0x054f, 0x24 }, { 0x0503, 0x25 },
|
|
{ 0x04bb, 0x26 }, { 0x0477, 0x27 }, { 0x0436, 0x28 }, { 0x03fa, 0x29 }, { 0x03c1, 0x2a },
|
|
{ 0x0386, 0x2b }, { 0x0358, 0x30 }, { 0x0328, 0x31 }, { 0x02fa, 0x32 }, { 0x02d0, 0x33 },
|
|
{ 0x02a6, 0x34 }, { 0x0280, 0x35 }, { 0x025c, 0x36 }, { 0x023a, 0x37 }, { 0x021a, 0x38 },
|
|
{ 0x01fc, 0x39 }, { 0x01e0, 0x3a }, { 0x01c5, 0x3b }, { 0x01ac, 0x40 }, { 0x0194, 0x41 },
|
|
{ 0x017d, 0x42 }, { 0x0168, 0x43 }, { 0x0153, 0x44 }, { 0x0140, 0x45 }, { 0x012e, 0x46 },
|
|
{ 0x011d, 0x47 }, { 0x010d, 0x48 }, { 0x00fe, 0x49 }, { 0x00f0, 0x4a }, { 0x00e2, 0x4b },
|
|
{ 0x00d6, 0x50 }, { 0x00ca, 0x51 }, { 0x00be, 0x52 }, { 0x00b4, 0x53 }, { 0x00aa, 0x54 },
|
|
{ 0x00a0, 0x55 }, { 0x0097, 0x56 }, { 0x008f, 0x57 }, { 0x0087, 0x58 }, { 0x007f, 0x59 },
|
|
{ 0x0078, 0x5a }, { 0x0071, 0x5b }, { 0x006b, 0x60 }, { 0x0065, 0x61 }, { 0x005f, 0x62 },
|
|
{ 0x005a, 0x63 }, { 0x0055, 0x64 }, { 0x0050, 0x65 }, { 0x004c, 0x66 }, { 0x0047, 0x67 },
|
|
{ 0x0043, 0x68 }, { 0x003f, 0x69 }, { 0x003c, 0x6a }, { 0x0039, 0x6b }, { 0x0035, 0x70 },
|
|
{ 0x0032, 0x71 }, { 0x002f, 0x72 }, { 0x002d, 0x73 }, { 0x002a, 0x74 }, { 0x0028, 0x75 },
|
|
{ 0x0025, 0x76 }, { 0x0023, 0x77 }, { 0x0021, 0x78 }, { 0x001f, 0x79 }, { 0x001e, 0x7a },
|
|
{ 0x001c, 0x7b }, { 0x001a, 0x80 }, { 0x0019, 0x81 }, { 0x0017, 0x82 }, { 0x0016, 0x83 },
|
|
{ 0x0015, 0x84 }, { 0x0014, 0x85 }, { 0x0012, 0x86 }, { 0x0011, 0x87 }, { 0x0010, 0x88 },
|
|
{ 0x000f, 0x89 }, { 0x000f, 0x8a }, { 0x000e, 0x8b }, { 0x004b, 0x66 }, { 0x0474, 0x27 },
|
|
{ 0x0500, 0x25 }, { 0x05f4, 0x22 }, { 0x054c, 0x24 }, { 0x03f8, 0x29 },
|
|
{ 0x02b4, 0x34 }
|
|
};
|
|
|
|
|
|
static int getSamplesSize(MODFILE *mod) {
|
|
|
|
int i, s;
|
|
|
|
for (i = s = 0; i < mod->nSamples; i++)
|
|
s += mod->samples[i].sampleInfo.length;
|
|
|
|
return s;
|
|
}
|
|
|
|
static int calcNumOfPatterns(MODFILE *mod, int modlength) {
|
|
|
|
int n1, n2;
|
|
int i;
|
|
int patternsSize = 256 * (mod->nChannels - 1);
|
|
|
|
for (i = n1 = 0; i < mod->songlength; i++) {
|
|
|
|
if (mod->playlist[i] > n1)
|
|
n1 = mod->playlist[i];
|
|
}
|
|
n1++;
|
|
|
|
n2 = modlength - getSamplesSize(mod) - 1084;
|
|
|
|
return n2 % patternsSize == 0 ? n2 / patternsSize : n1;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* int MODFILE_SetMOD(u8 *modfile, int modlength, MODFILE *mod);
|
|
*
|
|
* Processes the raw data of a Protracker MOD file and copies
|
|
* it to a structure. The structure can then be used as a handle
|
|
* of the MOD file. The original raw data isn't needed by the
|
|
* handle.
|
|
*
|
|
* Returns a value <0 on error.
|
|
*
|
|
* Parameters:
|
|
* modfile - A pointer to the raw MOD data
|
|
* modlength - The length of the raw data in bytes
|
|
* mod - A pointer to the MOD handle
|
|
**/
|
|
int MODFILE_SetMOD(u8 *modfile, int modlength, MODFILE *mod) {
|
|
|
|
int ofs = 0;
|
|
int i;
|
|
int sampledatalen;
|
|
int retval = 0;
|
|
|
|
if (modfile == NULL || mod == NULL)
|
|
return -1;
|
|
|
|
mod->nInstruments = 31;
|
|
|
|
if ( (memcmp(&modfile[1080], "M.K.", 4) == 0) ||
|
|
(memcmp(&modfile[1080], "FLT4", 4) == 0) ) {
|
|
|
|
mod->nChannels = 4;
|
|
} else if (memcmp(&modfile[1080], "2CHN", 4) == 0) {
|
|
|
|
mod->nChannels = 2;
|
|
} else if (memcmp(&modfile[1080], "6CHN", 4) == 0) {
|
|
|
|
mod->nChannels = 6;
|
|
} else if (memcmp(&modfile[1080], "8CHN", 4) == 0) {
|
|
|
|
mod->nChannels = 8;
|
|
} else if (memcmp(&modfile[1080], "10CH", 4) == 0) {
|
|
|
|
mod->nChannels = 10;
|
|
} else if (memcmp(&modfile[1080], "12CH", 4) == 0) {
|
|
|
|
mod->nChannels = 12;
|
|
} else if (memcmp(&modfile[1080], "14CH", 4) == 0) {
|
|
|
|
mod->nChannels = 14;
|
|
} else if (memcmp(&modfile[1080], "16CH", 4) == 0) {
|
|
|
|
mod->nChannels = 16;
|
|
} else if (memcmp(&modfile[1080], "18CH", 4) == 0) {
|
|
|
|
mod->nChannels = 18;
|
|
} else if (memcmp(&modfile[1080], "20CH", 4) == 0) {
|
|
|
|
mod->nChannels = 20;
|
|
} else if (memcmp(&modfile[1080], "22CH", 4) == 0) {
|
|
|
|
mod->nChannels = 22;
|
|
} else if (memcmp(&modfile[1080], "24CH", 4) == 0) {
|
|
|
|
mod->nChannels = 24;
|
|
} else if (memcmp(&modfile[1080], "26CH", 4) == 0) {
|
|
|
|
mod->nChannels = 26;
|
|
} else if (memcmp(&modfile[1080], "28CH", 4) == 0) {
|
|
|
|
mod->nChannels = 28;
|
|
} else if (memcmp(&modfile[1080], "30CH", 4) == 0) {
|
|
|
|
mod->nChannels = 30;
|
|
} else if (memcmp(&modfile[1080], "32CH", 4) == 0) {
|
|
|
|
mod->nChannels = 32;
|
|
} else {
|
|
|
|
mod->nInstruments = 15;
|
|
mod->nChannels = 4;
|
|
}
|
|
|
|
mod->nChannels++; /* Global fx channel */
|
|
mod->nSamples = mod->nInstruments; /* The MOD format doesn't support multisamples */
|
|
|
|
/* 0 */
|
|
memcpy(mod->songname, &modfile[ofs], 20);
|
|
ofs += 20;
|
|
/* Instruments */
|
|
/* 20 */
|
|
/* mod->instruments = malloc(mod->nInstruments * sizeof(MOD_Instrument));*/
|
|
SAFE_MALLOC(mod->instruments, mod->nInstruments * sizeof(MOD_Instrument));
|
|
memset(mod->instruments, 0, mod->nInstruments * sizeof(MOD_Instrument));
|
|
/* mod->samples = malloc(mod->nSamples * sizeof(MOD_Sample));*/
|
|
SAFE_MALLOC(mod->samples, mod->nSamples * sizeof(MOD_Sample));
|
|
memset(mod->samples, 0, mod->nSamples * sizeof(MOD_Sample));
|
|
|
|
for (i = 0; i < mod->nInstruments; i++) {
|
|
|
|
int temp, j;
|
|
|
|
/* Name */
|
|
memcpy(mod->samples[i].name, &modfile[ofs], 22);
|
|
ofs += 22;
|
|
/* Length */
|
|
temp = modfile[ofs++] << 8;
|
|
temp |= modfile[ofs++];
|
|
temp *= 2;
|
|
mod->samples[i].sampleInfo.length = temp;
|
|
/* Fine tune */
|
|
temp = modfile[ofs++];
|
|
if (temp > 7) temp -= 16;
|
|
temp += 8;
|
|
mod->samples[i].default_middle_c = s3m_finetunes[temp];
|
|
/* Volume */
|
|
mod->samples[i].default_volume = modfile[ofs++];
|
|
/* Loop start */
|
|
temp = modfile[ofs++] << 8;
|
|
temp |= modfile[ofs++];
|
|
temp *= 2;
|
|
mod->samples[i].sampleInfo.loop_start = temp;
|
|
/* Loop end */
|
|
temp = modfile[ofs++] << 8;
|
|
temp |= modfile[ofs++];
|
|
temp *= 2;
|
|
mod->samples[i].sampleInfo.loop_end = mod->samples[i].sampleInfo.loop_start + temp;
|
|
|
|
mod->samples[i].panning = 255;
|
|
mod->samples[i].sampleInfo.bit_16 = FALSE;
|
|
mod->samples[i].sampleInfo.stereo = FALSE;
|
|
mod->samples[i].sampleInfo.pingpong = FALSE;
|
|
mod->samples[i].relative_note = 0;
|
|
|
|
mod->samples[i].sampleInfo.looped = TRUE;
|
|
if (temp <= 2) {
|
|
|
|
mod->samples[i].sampleInfo.looped = FALSE;
|
|
mod->samples[i].sampleInfo.loop_start = mod->samples[i].sampleInfo.loop_end =
|
|
mod->samples[i].sampleInfo.length - 1;
|
|
}
|
|
|
|
/* Define a new instrument */
|
|
strcpy(mod->instruments[i].name, mod->samples[i].name);
|
|
for (j = 0; j < 256; j++) {
|
|
|
|
mod->instruments[i].samples[j] = &mod->samples[i];
|
|
mod->instruments[i].note[j] = j;
|
|
}
|
|
|
|
/* Disable instrument envelopes */
|
|
mod->instruments[i].envPanning.enabled = FALSE;
|
|
mod->instruments[i].envVolume.enabled = FALSE;
|
|
mod->instruments[i].volumeFade = 32767;
|
|
}
|
|
|
|
/* Song length */
|
|
mod->songlength = modfile[ofs++];
|
|
/* CIAA speed */
|
|
ofs++;
|
|
/* Arrangement */
|
|
memcpy(mod->playlist, &modfile[ofs], 128);
|
|
ofs += 128;
|
|
/* I.D. */
|
|
if (mod->nInstruments != 15)
|
|
ofs += 4;
|
|
|
|
/* Calculate number of patterns */
|
|
mod->nPatterns = calcNumOfPatterns(mod, modlength);
|
|
/* for (i = mod->nPatterns = 0; i < mod->songlength; i++) {
|
|
|
|
if (mod->playlist[i] > mod->nPatterns)
|
|
mod->nPatterns = mod->playlist[i];
|
|
}
|
|
|
|
mod->nPatterns++;*/
|
|
|
|
/* Extract the patterns */
|
|
/* mod->patterns = malloc(sizeof(MOD_Note*) * mod->nPatterns);
|
|
mod->patternLengths = malloc(sizeof(int) * mod->nPatterns);*/
|
|
SAFE_MALLOC(mod->patterns, sizeof(MOD_Note*) * mod->nPatterns);
|
|
SAFE_MALLOC(mod->patternLengths, sizeof(int) * mod->nPatterns);
|
|
|
|
for (i = 0; i < mod->nPatterns; i++) {
|
|
|
|
int pline, pchannel;
|
|
u8 * curPattern;
|
|
|
|
mod->patternLengths[i] = 64;
|
|
|
|
/* Alloc mem for current pattern */
|
|
/* mod->patterns[i] = malloc(sizeof(MOD_Note) * mod->nChannels * 64);*/
|
|
SAFE_MALLOC(mod->patterns[i], sizeof(MOD_Note) * mod->nChannels * 64);
|
|
memset(mod->patterns[i], 255, sizeof(MOD_Note) * mod->nChannels * 64);
|
|
|
|
/* Convert MOD pattern to our format */
|
|
curPattern = &modfile[ofs];
|
|
for (pline = 0; pline < 64; pline++) {
|
|
|
|
u8 *curLine = &curPattern[(mod->nChannels - 1) * 4 * pline];
|
|
MOD_Note *globalEffect = &mod->patterns[i][(pline * mod->nChannels) + mod->nChannels - 1];
|
|
|
|
for (pchannel = 0; pchannel < mod->nChannels - 1; pchannel++) {
|
|
|
|
int j;
|
|
u8 *curNote = &curLine[4 * pchannel];
|
|
u16 note;
|
|
u8 dnote;
|
|
u32 instrument;
|
|
u16 effect;
|
|
u8 operand;
|
|
u8 volume;
|
|
|
|
note = (curNote[0] & 0x0f) << 8;
|
|
note |= curNote[1];
|
|
instrument = curNote[0] & 0xf0;
|
|
instrument |= (curNote[2] & 0xf0) >> 4;
|
|
effect = curNote[2] & 0x0f;
|
|
operand = curNote[3];
|
|
volume = 255;
|
|
|
|
/* Convert note */
|
|
dnote = 0xff;
|
|
if (note != 0) {
|
|
|
|
for (j = 0; j < NUM_AMIGA_FREQS; j++) {
|
|
|
|
if (s3m_amiga2st3[j].amigafreq == note)
|
|
dnote = s3m_amiga2st3[j].st3note;
|
|
}
|
|
}
|
|
|
|
if ((dnote == 0xff) && (note != 0)) { /* Note not found */
|
|
|
|
fprintf(stderr, "Note not found: %x\n", note);
|
|
|
|
retval = 1;
|
|
}
|
|
|
|
/* Convert effect */
|
|
switch (effect) {
|
|
|
|
case 0x00: /* Arpeggio */
|
|
if (operand != 0)
|
|
effect = EFFECT_ST00;
|
|
else
|
|
effect = EFFECT_NONE;
|
|
break;
|
|
case 0x01: /* Porta up */
|
|
effect = EFFECT_ST10;
|
|
break;
|
|
case 0x02: /* Porta down */
|
|
effect = EFFECT_ST20;
|
|
break;
|
|
case 0x03: /* Porta to note */
|
|
effect = EFFECT_ST30;
|
|
break;
|
|
case 0x04: /* Vibrato */
|
|
effect = EFFECT_ST40;
|
|
break;
|
|
case 0x05: /* Porta + volume slide */
|
|
effect = EFFECT_ST50;
|
|
break;
|
|
case 0x06: /* Vibrato + volume slide */
|
|
effect = EFFECT_ST60;
|
|
break;
|
|
case 0x07: /* Tremolo */
|
|
effect = EFFECT_ST70;
|
|
break;
|
|
case 0x09: /* Sample offset */
|
|
effect = EFFECT_ST90;
|
|
break;
|
|
case 0x0a: /* Volume slide */
|
|
effect = EFFECT_STa0;
|
|
break;
|
|
case 0x0b: /* Pattern jump */
|
|
globalEffect->effect[0] = EFFECT_STb0;
|
|
globalEffect->operand[0] = operand;
|
|
effect = EFFECT_NONE;
|
|
operand = 0;
|
|
break;
|
|
case 0x0c: /* Set volume */
|
|
effect = EFFECT_NONE;
|
|
if (operand > 64)
|
|
operand = 64;
|
|
volume = operand;
|
|
break;
|
|
case 0x0d: /* Pattern break */
|
|
operand = ((operand >> 4) * 10) + (operand & 0x0f);
|
|
if (operand >= 64)
|
|
operand = 0;
|
|
|
|
if (globalEffect->effect[0] == EFFECT_STb0) {
|
|
|
|
globalEffect->effect[0] = EFFECT_STg0;
|
|
globalEffect->operand[1] = operand;
|
|
} else {
|
|
|
|
globalEffect->effect[0] = EFFECT_STd0;
|
|
globalEffect->operand[0] = operand;
|
|
}
|
|
effect = EFFECT_NONE;
|
|
operand = 0;
|
|
break;
|
|
case 0x0e:
|
|
switch (operand >> 4) {
|
|
|
|
int temp;
|
|
|
|
case 0x01: /* Fine porta up */
|
|
effect = EFFECT_STe1;
|
|
operand = operand & 0x0f;
|
|
break;
|
|
case 0x02: /* Fine porta down */
|
|
effect = EFFECT_STe2;
|
|
operand = operand & 0x0f;
|
|
break;
|
|
case 0x04: /* Set vibrato waveform */
|
|
effect = EFFECT_STe4;
|
|
operand = operand & 0x0f;
|
|
break;
|
|
case 0x05: /* Set finetune */
|
|
effect = EFFECT_STe5;
|
|
temp = operand & 0x0f;
|
|
if (temp > 7) temp -= 16;
|
|
temp += 8;
|
|
operand = operand & 0x0f;
|
|
break;
|
|
case 0x06: /* Pattern loop */
|
|
operand = operand & 0x0f;
|
|
globalEffect->effect[0] = EFFECT_STe6;
|
|
globalEffect->operand[0] = operand;
|
|
effect = EFFECT_NONE;
|
|
operand = 0;
|
|
break;
|
|
case 0x07: /* Set tremolo waveform */
|
|
effect = EFFECT_STe7;
|
|
operand = operand & 0x0f;
|
|
break;
|
|
case 0x08: /* Panning */
|
|
effect = EFFECT_STe8;
|
|
operand = operand & 0x0f;
|
|
break;
|
|
case 0x09: /* Retrig */
|
|
effect = EFFECT_STe9;
|
|
operand = operand & 0x0f;
|
|
break;
|
|
case 0x0a: /* Fine volume slide up */
|
|
effect = EFFECT_STea;
|
|
operand = operand & 0x0f;
|
|
break;
|
|
case 0x0b: /* Fine volume slide down */
|
|
effect = EFFECT_STeb;
|
|
operand = operand & 0x0f;
|
|
break;
|
|
case 0x0c: /* Note cut */
|
|
effect = EFFECT_STec;
|
|
operand = operand & 0x0f;
|
|
break;
|
|
case 0x0d: /* Note delay */
|
|
effect = EFFECT_STed;
|
|
operand = operand & 0x0f;
|
|
break;
|
|
case 0x0e: /* Pattern delay */
|
|
operand = operand & 0x0f;
|
|
globalEffect->effect[0] = EFFECT_STee;
|
|
globalEffect->operand[0] = operand;
|
|
effect = EFFECT_NONE;
|
|
operand = 0;
|
|
break;
|
|
default:
|
|
effect = EFFECT_NONE;
|
|
break;
|
|
}
|
|
break;
|
|
case 0x0f: /* Set speed/tempo */
|
|
/* if (operand < 32)
|
|
effect = 'A' - 'A' + 1;
|
|
else
|
|
effect = 'T' - 'A' + 1;*/
|
|
effect = EFFECT_STf0;
|
|
break;
|
|
default:
|
|
effect = EFFECT_NONE;
|
|
break;
|
|
}
|
|
|
|
j = (pline * mod->nChannels) + pchannel;
|
|
mod->patterns[i][j].note = dnote;
|
|
mod->patterns[i][j].instrument = instrument;
|
|
mod->patterns[i][j].volume = volume;
|
|
mod->patterns[i][j].effect[0] = effect;
|
|
mod->patterns[i][j].operand[0] = operand;
|
|
}
|
|
}
|
|
|
|
ofs += 4 * (mod->nChannels - 1) * 64;
|
|
}
|
|
|
|
/* Sample data */
|
|
for (i = sampledatalen = 0; i < mod->nInstruments; i++) {
|
|
|
|
sampledatalen += mod->samples[i].sampleInfo.length;
|
|
}
|
|
|
|
if ((sampledatalen + 1084 + (mod->nPatterns * 64 * (mod->nChannels - 1) * 4)) != modlength) {
|
|
|
|
ofs = modlength - sampledatalen;
|
|
}
|
|
|
|
for (i = 0; i < mod->nInstruments; i++) {
|
|
|
|
mod->samples[i].sampleInfo.sampledata = NULL;
|
|
if (mod->samples[i].sampleInfo.length != 0) {
|
|
|
|
/* mod->samples[i].sampleInfo.sampledata = malloc(mod->samples[i].sampleInfo.length);*/
|
|
SAFE_MALLOC(mod->samples[i].sampleInfo.sampledata, mod->samples[i].sampleInfo.length);
|
|
memcpy(mod->samples[i].sampleInfo.sampledata, &modfile[ofs], mod->samples[i].sampleInfo.length);
|
|
ofs += mod->samples[i].sampleInfo.length;
|
|
}
|
|
}
|
|
|
|
for ( i = 0; i < mod->nChannels; i++) {
|
|
|
|
mod->channels[i].voiceInfo.enabled = TRUE;
|
|
mod->channels[i].default_panning = (((i - 1) >> 1) & 1) ^ 1 ? 86 : 167;
|
|
}
|
|
|
|
mod->start_speed = 6;
|
|
mod->start_tempo = 125;
|
|
mod->master_volume = 64;
|
|
|
|
mod->filetype = MODULE_MOD;
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* BOOL MODFILE_IsMOD(u8 *modfile, int modlength);
|
|
*
|
|
* Checks whether the raw data in memory is a valid
|
|
* Protracker MOD file.
|
|
*
|
|
* Returns TRUE if the data is a Protracker MOD,
|
|
* FALSE if not.
|
|
*
|
|
* Parameters:
|
|
*
|
|
* modfile - Pointer to the raw data to be checked
|
|
* modlength - Length of the raw data in bytes
|
|
**/
|
|
BOOL MODFILE_IsMOD(u8 *modfile, int modlength) {
|
|
|
|
MODFILE temp;
|
|
int ret;
|
|
|
|
if ((modfile == NULL) || (modlength < 1080))
|
|
return FALSE;
|
|
|
|
MODFILE_Init(&temp);
|
|
|
|
if ((ret = MODFILE_SetMOD(modfile, modlength, &temp)) >= 0) {
|
|
|
|
temp.set = TRUE;
|
|
MODFILE_Free(&temp);
|
|
}
|
|
|
|
return ret == 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
int MODFILE_MODGetFormatID(void) {
|
|
|
|
return MODULE_MOD;
|
|
}
|
|
|
|
char *MODFILE_MODGetDescription(void) {
|
|
|
|
return DESCRIPTION;
|
|
}
|
|
|
|
char *MODFILE_MODGetAuthor(void) {
|
|
|
|
return AUTHOR;
|
|
}
|
|
|
|
char *MODFILE_MODGetVersion(void) {
|
|
|
|
return VERSION;
|
|
}
|
|
|
|
char *MODFILE_MODGetCopyright(void) {
|
|
|
|
return COPYRIGHT;
|
|
}
|