summaryrefslogtreecommitdiff
path: root/plugins/dumb/dumb-kode54/src/tools/it/load_it.cpp
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-05-27 22:51:35 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-05-27 22:51:35 +0200
commit4810f9a0af507bb405e6a3c58decfa9c9980b2ff (patch)
tree75ac9c06345b23528e6771bb1bae697ff5c29c1c /plugins/dumb/dumb-kode54/src/tools/it/load_it.cpp
parentad71971955594ada4a0b14d176a192d050c9ee36 (diff)
merged parts of DUMB-0.9.3
Diffstat (limited to 'plugins/dumb/dumb-kode54/src/tools/it/load_it.cpp')
-rw-r--r--plugins/dumb/dumb-kode54/src/tools/it/load_it.cpp1648
1 files changed, 824 insertions, 824 deletions
diff --git a/plugins/dumb/dumb-kode54/src/tools/it/load_it.cpp b/plugins/dumb/dumb-kode54/src/tools/it/load_it.cpp
index ed88e706..bc749cb5 100644
--- a/plugins/dumb/dumb-kode54/src/tools/it/load_it.cpp
+++ b/plugins/dumb/dumb-kode54/src/tools/it/load_it.cpp
@@ -1,824 +1,824 @@
-#ifdef FORTIFY
-#include "fortify.h"
-#endif
-#include <stdio.h>
-#ifdef MSS
-#include "mss.h"
-#endif
-
-#include <string.h>
-
-#include "allegro.h"
-#include "modulus.h"
-#include "typedef.hpp"
-
-int detect_it(char *f) {
- int sig;
- PACKFILE *fn = pack_fopen(f, "rb");
-
- if (fn == NULL)
- return FALSE;
-
- sig = pack_mgetl(fn);
- if (sig != AL_ID('I','M','P','M')) {
- pack_fclose(fn);
- return FALSE;
- }
- pack_fclose(fn);
-
- return TRUE;
-}
-
-MODULUS *create_it() {
- MODULUS *m = (MODULUS*)malloc(sizeof(MODULUS));
- if (!m)
- return NULL;
- memset(m, 0, sizeof(MODULUS));
- return m;
-}
-
-void destroy_it(MODULUS *j) {
-
- if (song->Music == j)
- stop_it();
-
- //remove patterns:
- for (int i=0; i<j->NumPatterns; i++) {
- free(j->Pattern[i].Note);
- }
- if (j->Pattern)
- free(j->Pattern);
- //remove instruments;
- if (j->Instrument)
- free(j->Instrument);
- //remove samples;
- for (int i=0; i<j->NumSamples; i++) {
- destroy_sample(j->Sample[i].Sample);
- }
- if (j->Sample)
- free(j->Sample);
- //remove orders:
- if (j->Order)
- free(j->Order);
- //remove channels:
- for (int i=0; i<64; i++) {
- if (j->Channel[i].VChannel) {
- MODULUS_VCHANNEL *vchn = song->Music->Channel[i].VChannel;
- MODULUS_VCHANNEL *prev = NULL;
-
- if (!vchn)
- continue;
-
- for (;;) {
- deallocate_voice(vchn->voice);
-
- prev = vchn;
- vchn = vchn->next;
- free(prev);
-
- if (!vchn)
- break;
- }
- }
- }
- free(j);
-}
-
-//#define DEBUG_IT_SIZE
-
-int get_module_size(MODULUS *j) {
- int a, b, c, d = 0, e;
- a = sizeof(MODULUS) + j->NumOrders;
- b = j->NumInstruments * sizeof(MODULUS_INSTRUMENT);
- c = j->NumSamples * sizeof(MODULUS_SAMPLE);
-
- for (int i=0; i<j->NumSamples; i++)
- d += j->Sample[i].SampleLength * (j->Sample[i].Flag & 2 ? sizeof(short) : 1) * (j->Sample[i].Flag & 4 ? 2: 1);
-
- e = 4 + sizeof(MODULUS_PATTERN) * j->NumPatterns;
-
- for (int i=0; i<j->NumPatterns; i++)
- e += j->Pattern[i].NumNotes * sizeof(MODULUS_NOTE);
- #ifdef DEBUG_IT_SIZE
- printf("Base: %i, Instruments(%i): %i, Samples(%i): %i, Data: %i, Patterns(%i): %i\n", a, j->NumInstruments, b, j->NumSamples, c, d, j->NumPatterns, e);
- #endif
-
- return a+b+c+d+e;
-}
-
-#define MAX_IT_CHN 64
-
-//#define DEBUG_HEADER
-//#define DEBUG_INSTRUMENTS
-//#define DEBUG_SAMPLES
-//#define DEBUG_PATTERNS
-
-static dword *sourcebuf = NULL;
-static dword *sourcepos = NULL;
-static byte rembits = 0;
-
-int readblock(PACKFILE *f) {
- long size;
- int c = pack_igetw(f);
- if (c == -1)
- return 0;
- size = c;
-
- sourcebuf = (dword*)malloc(size+4);
- if (!sourcebuf)
- return 0;
-
- c = pack_fread(sourcebuf, size, f);
- if (c < 1) {
- free(sourcebuf);
- sourcebuf = NULL;
- return 0;
- }
- sourcepos = sourcebuf;
- rembits = 32;
- return 1;
-}
-
-void freeblock() {
- if (sourcebuf)
- free(sourcebuf);
- sourcebuf = NULL;
-}
-
-dword readbits(char b) {
- dword val;
- if (b <= rembits) {
- val = *sourcepos & ((1 << b) - 1);
- *sourcepos >>= b;
- rembits -= b;
- }
- else {
- dword nbits = b - rembits;
- val = *sourcepos;
- sourcepos++;
- val |= ((*sourcepos & ((1 << nbits) - 1)) << rembits);
- *sourcepos >>= nbits;
- rembits = 32 - nbits;
- }
- return val;
-}
-
-void decompress8(PACKFILE *f, void *data, int len, int tver) {
- char *destbuf = (char*)data;
- char *destpos = destbuf;
- int blocklen, blockpos;
- byte bitwidth;
- word val;
- char d1, d2;
-
- memset(destbuf, 0, len);
-
- while (len>0) {
- //Read a block of compressed data:
- if (!readblock(f))
- return;
- //Set up a few variables
- blocklen = (len < 0x8000) ? len : 0x8000; //Max block length is 0x8000 bytes
- blockpos = 0;
- bitwidth = 9;
- d1 = d2 = 0;
- //Start the decompression:
- while (blockpos < blocklen) {
- //Read a value:
- val = readbits(bitwidth);
- //Check for bit width change:
-
- if (bitwidth < 7) { //Method 1:
- if (val == (1 << (bitwidth - 1))) {
- val = readbits(3) + 1;
- bitwidth = (val < bitwidth) ? val : val + 1;
- continue;
- }
- }
- else if (bitwidth < 9) { //Method 2
- byte border = (0xFF >> (9 - bitwidth)) - 4;
-
- if (val > border && val <= (border + 8)) {
- val -= border;
- bitwidth = (val < bitwidth) ? val : val + 1;
- continue;
- }
- }
- else if (bitwidth == 9) { //Method 3
- if (val & 0x100) {
- bitwidth = (val + 1) & 0xFF;
- continue;
- }
- }
- else { //Illegal width, abort ?
- freeblock();
- return;
- }
-
- //Expand the value to signed byte:
- char v; //The sample value:
- if (bitwidth < 8) {
- byte shift = 8 - bitwidth;
- v = (val << shift);
- v >>= shift;
- }
- else
- v = (char)val;
-
- //And integrate the sample value
- //(It always has to end with integration doesn't it ? ;-)
- d1 += v;
- d2 += d1;
-
- //Store !
- *destpos = ((tver == 0x215) ? d2 : d1);
- destpos++;
- blockpos++;
- }
- freeblock();
- len -= blocklen;
- }
- return;
-}
-
-void decompress16(PACKFILE *f, void *data, int len, int tver) {
- //make the output buffer:
- short *destbuf = (short*)data;
- short *destpos = destbuf;
- int blocklen, blockpos;
- byte bitwidth;
- long val;
- short d1, d2;
-
- memset(destbuf, 0, len);
-
- while (len>0) {
- //Read a block of compressed data:
- if (!readblock(f))
- return;
- //Set up a few variables
- blocklen = (len < 0x4000) ? len : 0x4000; // Max block length is 0x4000 bytes
- blockpos = 0;
- bitwidth = 17;
- d1 = d2 = 0;
- //Start the decompression:
- while (blockpos < blocklen) {
- val = readbits(bitwidth);
- //Check for bit width change:
-
- if (bitwidth < 7) { //Method 1:
- if (val == (1 << (bitwidth - 1))) {
- val = readbits(4) + 1;
- bitwidth = (val < bitwidth) ? val : val + 1;
- continue;
- }
- }
- else if (bitwidth < 17) { //Method 2
- word border = (0xFFFF >> (17 - bitwidth)) - 8;
-
- if (val > border && val <= (border + 16)) {
- val -= border;
- bitwidth = val < bitwidth ? val : val + 1;
- continue;
- }
- }
- else if (bitwidth == 17) { //Method 3
- if (val & 0x10000) {
- bitwidth = (val + 1) & 0xFF;
- continue;
- }
- }
- else { //Illegal width, abort ?
- freeblock();
- return;
- }
-
- //Expand the value to signed byte:
- short v; //The sample value:
- if (bitwidth < 16) {
- byte shift = 16 - bitwidth;
- v = (val << shift);
- v >>= shift;
- }
- else
- v = (short)val;
-
- //And integrate the sample value
- //(It always has to end with integration doesn't it ? ;-)
- d1 += v;
- d2 += d1;
-
- //Store !
- *destpos = ((tver == 0x215) ? d2 : d1);
- destpos++;
- blockpos++;
- }
- freeblock();
- len -= blocklen;
- }
- return;
-}
-
-MODULUS *load_it(char *file) {
- PACKFILE *f;
- MODULUS *j = create_it();
- int tver, tver2, flag, msglen, msgoffs;
- int *insoffs = NULL, *samoffs = NULL, *patoffs = NULL;
-
- if (!j)
- return NULL;
-
- if (!detect_it(file))
- return NULL;
-
- f = pack_fopen(file, "rb");
-
- if (!f) {
- #ifdef DEBUG_HEADER
- printf("Error Opening!\n");
- #endif
- return NULL;
- }
-
- pack_fseek(f, 30);
- pack_igetw(f); //I have no idea...
-
- j->NumOrders = pack_igetw(f);
- j->NumInstruments = pack_igetw(f);
- j->NumSamples = pack_igetw(f);
- j->NumPatterns = pack_igetw(f);
-
- #ifdef DEBUG_HEADER
- printf("Loading IT: %i Orders %i Instruments, %i Samples, %i Patterns\n", j->NumOrders, j->NumInstruments, j->NumSamples, j->NumPatterns);
- #endif
-
- tver = pack_igetw(f);
- j->Version = tver2 = pack_igetw(f);
-
- #ifdef DEBUG_HEADER
- printf("Tracker ver: %X, %X\n", tver, tver2);
- #endif
-
- j->Flags = pack_igetw(f);
- flag = pack_igetw(f);
-
- j->GlobalVolume = pack_getc(f);
- j->MixVolume = pack_getc(f);
- j->Speed = pack_getc(f);
- j->Tempo = pack_getc(f);
- j->PanningSeperation = pack_getc(f);
-
- #ifdef DEBUG_HEADER
- printf("Global Volume: %i, Mixing Volume: %i, Speed: %i, Tempo: %i, PanSep: %i\n", j->GlobalVolume, j->MixVolume, j->Speed, j->Tempo, j->PanningSeperation);
- #endif
-
- pack_getc(f); //Damn....I need more info on this.
-
- msglen = pack_igetw(f);
- msgoffs = pack_igetl(f);
-
- pack_fseek(f, 4);
-
- #ifdef DEBUG_HEADER
- printf("Channel Pan:");
- #endif
-
- for (int i=0; i<MAX_IT_CHN; i++) {
- j->Channel[i].Pan = pack_getc(f);
- #ifdef DEBUG_HEADER
- printf(" %i", j->Channel[i].Pan);
- #endif
- }
- #ifdef DEBUG_HEADER
- printf("\nChannel Vol:");
- #endif
- for (int i=0; i<MAX_IT_CHN; i++) {
- j->Channel[i].Volume = pack_getc(f);
- #ifdef DEBUG_HEADER
- printf(" %i", j->Channel[i].Volume);
- #endif
- }
- #ifdef DEBUG_HEADER
- printf("\n");
- #endif
-
- j->Order = (unsigned char *)malloc(j->NumOrders);
- pack_fread(j->Order, j->NumOrders, f);
-
- if (j->NumInstruments)
- insoffs = (int*)malloc(4 * j->NumInstruments);
- if (j->NumSamples)
- samoffs = (int*)malloc(4 * j->NumSamples);
- if (j->NumPatterns)
- patoffs = (int*)malloc(4 * j->NumPatterns);
-
- pack_fread(insoffs, 4 * j->NumInstruments, f);
- pack_fread(samoffs, 4 * j->NumSamples, f);
- pack_fread(patoffs, 4 * j->NumPatterns, f);
-
- if (flag&1) { //Song message attached
- //Ignore.
- }
- if (flag & 4) { //skip something:
- short u;
- char dummy[8];
- u = pack_igetw(f);
- for (int i=0; i<u; u++)
- pack_fread(dummy, 8, f);
- }
- if (flag & 8) { //MIDI commands ???
- char dummy[33];
- for (int i=0; i<9+16+128; i++)
- pack_fread(dummy, 32, f);
-
- }
-
- if (j->NumInstruments)
- j->Instrument = (MODULUS_INSTRUMENT*)malloc(sizeof(MODULUS_INSTRUMENT) * j->NumInstruments);
- #ifdef DEBUG_INSTRUMENTS
- if (!j->Instrument)
- printf("No Mem for Instruments!\n");
- #endif
-
-
- for (int i=0; i<j->NumInstruments; i++) {
- pack_fclose(f);
- f = pack_fopen(file, "rb");
- #ifdef DEBUG_INSTRUMENTS
- if (!f)
- printf("Error Opening!\n");
- #endif
- pack_fseek(f, insoffs[i] + 17);
-
- j->Instrument[i].NewNoteAction = pack_getc(f);
- j->Instrument[i].DuplicateCheckType = pack_getc(f);
- j->Instrument[i].DuplicateCheckAction = pack_getc(f);
- j->Instrument[i].FadeOut = pack_igetw(f);
- j->Instrument[i].PitchPanSeperation = pack_getc(f);
- j->Instrument[i].PitchPanCenter = pack_getc(f);
- j->Instrument[i].GlobalVolume = pack_getc(f);
- j->Instrument[i].DefaultPan = pack_getc(f);
- #ifdef DEBUG_INSTRUMENTS
- printf("I%02i @ 0x%X, NNA %i, DCT %i, DCA %i, FO %i, PPS %i, PPC %i, GVol %i, DPan %i\n", i, insoffs[i], j->Instrument[i].NewNoteAction, j->Instrument[i].DuplicateCheckType, j->Instrument[i].DuplicateCheckAction, j->Instrument[i].FadeOut, j->Instrument[i].PitchPanSeperation, j->Instrument[i].PitchPanCenter, j->Instrument[i].GlobalVolume, j->Instrument[i].DefaultPan);
- #endif
-
- pack_fseek(f, 38);
-
- for (int k=0; k<120; k++) {
- j->Instrument[i].NoteNote[k] = pack_getc(f);
- j->Instrument[i].NoteSample[k] = pack_getc(f) - 1;
- }
-
- j->Instrument[i].VolumeEnvelope.Flag = pack_getc(f);
- j->Instrument[i].VolumeEnvelope.NumNodes = pack_getc(f);
- j->Instrument[i].VolumeEnvelope.LoopBegin = pack_getc(f);
- j->Instrument[i].VolumeEnvelope.LoopEnd = pack_getc(f);
- j->Instrument[i].VolumeEnvelope.SustainLoopBegin = pack_getc(f);
- j->Instrument[i].VolumeEnvelope.SustainLoopEnd = pack_getc(f);
- for (int k=0; k<j->Instrument[i].VolumeEnvelope.NumNodes; k++) {
- j->Instrument[i].VolumeEnvelope.NodeY[k] = pack_getc(f);
- j->Instrument[i].VolumeEnvelope.NodeTick[k] = pack_igetw(f);
- }
- pack_fseek(f, 75 - j->Instrument[i].VolumeEnvelope.NumNodes * 3);
-
- j->Instrument[i].PanningEnvelope.Flag = pack_getc(f);
- j->Instrument[i].PanningEnvelope.NumNodes = pack_getc(f);
- j->Instrument[i].PanningEnvelope.LoopBegin = pack_getc(f);
- j->Instrument[i].PanningEnvelope.LoopEnd = pack_getc(f);
- j->Instrument[i].PanningEnvelope.SustainLoopBegin = pack_getc(f);
- j->Instrument[i].PanningEnvelope.SustainLoopEnd = pack_getc(f);
- for (int k=0; k<j->Instrument[i].PanningEnvelope.NumNodes; k++) {
- j->Instrument[i].PanningEnvelope.NodeY[k] = pack_getc(f);
- j->Instrument[i].PanningEnvelope.NodeTick[k] = pack_igetw(f);
- }
- pack_fseek(f, 75 - j->Instrument[i].PanningEnvelope.NumNodes * 3);
-
- j->Instrument[i].PitchEnvelope.Flag = pack_getc(f);
- j->Instrument[i].PitchEnvelope.NumNodes = pack_getc(f);
- j->Instrument[i].PitchEnvelope.LoopBegin = pack_getc(f);
- j->Instrument[i].PitchEnvelope.LoopEnd = pack_getc(f);
- j->Instrument[i].PitchEnvelope.SustainLoopBegin = pack_getc(f);
- j->Instrument[i].PitchEnvelope.SustainLoopEnd = pack_getc(f);
- for (int k=0; k<j->Instrument[i].PitchEnvelope.NumNodes; k++) {
- j->Instrument[i].PitchEnvelope.NodeY[k] = pack_getc(f);
- j->Instrument[i].PitchEnvelope.NodeTick[k] = pack_igetw(f);
- }
- }
-
- if (j->NumSamples)
- j->Sample = (MODULUS_SAMPLE*)malloc(sizeof(MODULUS_SAMPLE) * j->NumSamples);
-
- #ifdef DEBUG_SAMPLES
- if (!j->Sample)
- printf("No Mem for Samples!\n");
- #endif
-
- for (int i=0; i<j->NumSamples; i++) {
- int sam_samptr, convert;
-
- pack_fclose(f);
- f = pack_fopen(file, "rb");
- #ifdef DEBUG_SAMPLES
- if (!f)
- printf("Error opening!\n");
- #endif
-
- pack_fseek(f, samoffs[i] + 17);
-
- j->Sample[i].GlobalVolume = pack_getc(f);
- j->Sample[i].Flag = pack_getc(f);
- j->Sample[i].Volume = pack_getc(f);
-
- #ifdef DEBUG_SAMPLES
- printf("S%02i @ 0x%X, Vol: %i/%i, Flag: %i", i, samoffs[i], j->Sample[i].GlobalVolume, j->Sample[i].Volume, j->Sample[i].Flag);
- #endif
-
- pack_fseek(f, 26);
-
- convert = pack_getc(f);
- pack_getc(f); //Panning ?
-
- j->Sample[i].SampleLength = pack_igetl(f);
- j->Sample[i].LoopBegin = pack_igetl(f);
- j->Sample[i].LoopEnd = pack_igetl(f);
- j->Sample[i].C5Speed = pack_igetl(f);
- j->Sample[i].SustainLoopBegin = pack_igetl(f);
- j->Sample[i].SustainLoopEnd = pack_igetl(f);
-
- #ifdef DEBUG_SAMPLES
- printf(", SLen: %i, LpB: %i, LpE: %i, C5S: %i\n", j->Sample[i].SampleLength, j->Sample[i].LoopBegin, j->Sample[i].LoopEnd, j->Sample[i].C5Speed);
- #endif
-
- sam_samptr = pack_igetl(f);
-
- j->Sample[i].VibratoSpeed = pack_getc(f);
- j->Sample[i].VibratoDepth = pack_getc(f);
- j->Sample[i].VibratoRate = pack_getc(f);
- j->Sample[i].VibratoWaveForm = pack_getc(f);
-
- #ifdef DEBUG_SAMPLES
- printf("SusLpB: %i, SusLpE: %i, VibSp: %i, VibDep: %i, VibWav: %i, VibRat: %i\n", j->Sample[i].SustainLoopBegin, j->Sample[i].SustainLoopEnd, j->Sample[i].VibratoSpeed, j->Sample[i].VibratoDepth, j->Sample[i].VibratoWaveForm, j->Sample[i].VibratoRate);
- #endif
-
- if (j->Sample[i].Flag & 1 == 0)
- continue;
-
- pack_fclose(f);
- f = pack_fopen(file, "rb");
- pack_fseek(f, sam_samptr);
-
- int len = j->Sample[i].SampleLength * (j->Sample[i].Flag & 2 ? sizeof(short) : 1) * (j->Sample[i].Flag & 4 ? 2: 1);
-
- #ifdef DEBUG_SAMPLES
- printf("Len: %i, Size: %i KB\n", j->Sample[i].SampleLength, len/1024);
- #endif
-
- SAMPLE *sam = create_sample(j->Sample[i].Flag & 2 ? 16 : 8, j->Sample[i].Flag & 4 ? TRUE : FALSE, j->Sample[i].C5Speed, j->Sample[i].SampleLength);
-
- if (j->Sample[i].Flag & 8) { // If the sample is packed, then we must unpack it
- if (j->Sample[i].Flag & 2)
- decompress16(f, sam->data, j->Sample[i].SampleLength, tver2);
- else
- decompress8(f, sam->data, j->Sample[i].SampleLength, tver2);
- } else {
- pack_fread(sam->data, len, f);
- }
-
- if (j->Sample[i].Flag & SAMPLE_USELOOP) {
- sam->loop_start = j->Sample[i].LoopBegin;
- sam->loop_end = j->Sample[i].LoopEnd;
- }
-
- j->Sample[i].Sample = sam;
-
- void *dat = sam->data;
-
- if (convert & 2) { //Change the byte order for 16-bit samples:
- if (sam->bits == 16) {
- for (int k=0; k<len; k+=2) {
- int l = ((char*)dat)[k];
- ((char*)dat)[k] = ((char*)dat)[k+1];
- ((char*)dat)[k+1] = l;
-
- }
- }
- else {
- for (int k=0; k<len; k+=2) {
- int l = ((char*)dat)[k];
- ((char*)dat)[k] = ((char*)dat)[k+1];
- ((char*)dat)[k+1] = l;
-
- }
- }
- }
- if (convert & 1) { //Convert to unsigned
- if (sam->bits == 8) {
- for (int k=0; k<len; k++) {
- ((char*)dat)[k] ^= 0x80;
- }
- }
- else {
- for (int k=0; k<(len>>1); k++) {
- ((short*)dat)[k] ^= 0x8000;
- }
- }
- }
- }
-
- if (j->NumPatterns)
- j->Pattern = (MODULUS_PATTERN*)malloc(sizeof(MODULUS_PATTERN) * j->NumPatterns);
- unsigned char *buf = (unsigned char*)alloca(65536);
- unsigned char *cmask = (unsigned char*)alloca(64),
- *cnote = (unsigned char*)alloca(64),
- *cinstrument = (unsigned char*)alloca(64),
- *cvol = (unsigned char*)alloca(64),
- *ccom = (unsigned char*)alloca(64),
- *ccomval = (unsigned char*)alloca(64);
-
- for (int i=0; i<j->NumPatterns; i++) {
- int numnotes = 0, len, pos = 0, mask = 0, chn = 0;
-
- memset(cmask, 0, 64);
- memset(cnote, 0, 64);
- memset(cinstrument, 0, 64);
- memset(cvol, 0, 64);
- memset(ccom, 0, 64);
- memset(ccomval, 0, 64);
-
- pack_fclose(f);
- f = pack_fopen(file, "rb");
- pack_fseek(f, patoffs[i]);
-
- len = pack_igetw(f);
- j->Pattern[i].NumRows = pack_igetw(f);
-
- pack_fseek(f, 4);
- pack_fread(buf, len, f);
-
- while (pos < len) {
- int b = buf[pos];
- pos++;
- if (!b) { //If end of row:
- numnotes++;
- continue;
- }
- chn = (b - 1) & 63;
-
- if (b & 128) {
- mask = buf[pos];
- pos++;
- cmask[chn] = mask;
- }
- else
- mask = cmask[chn];
-
- if (mask)
- numnotes++;
- if (mask & 1)
- pos++;
- if (mask & 2)
- pos++;
- if (mask & 4)
- pos++;
- if (mask & 8)
- pos+=2; //Guessing here
- }
- j->Pattern[i].NumNotes = numnotes;
- j->Pattern[i].Note = (MODULUS_NOTE*)malloc(sizeof(MODULUS_NOTE) * numnotes);
- memset(j->Pattern[i].Note, 0, sizeof(MODULUS_NOTE) * numnotes);
-
- pos = 0;
- memset(cmask, 0, 64);
- mask = 0;
- numnotes = 0;
- while (pos < len) {
- int b = buf[pos];
- #ifdef DEBUG_PATTERNS
- printf("NumNote: %i ", numnotes);
- #endif
-
- pos++;
- if (!b) { //If end of row:
- j->Pattern[i].Note[numnotes].Channel = -1;
- numnotes++;
- #ifdef DEBUG_PATTERNS
- printf("Channel: -1\n");
- #endif
- continue;
- }
- chn = (b - 1) & 63;
-
- if (b & 128) {
- mask = buf[pos];
- pos++;
- cmask[chn] = mask;
- }
- else
- mask = cmask[chn];
- #ifdef DEBUG_PATTERNS
- printf("Channel: %i Mask: %i ", chn, mask);
- #endif
-
- if (mask)
- j->Pattern[i].Note[numnotes].Channel = chn;
-
- if (mask & 1) {
- j->Pattern[i].Note[numnotes].Note = buf[pos];
- j->Pattern[i].Note[numnotes].Mask |= 1;
- cnote[chn] = buf[pos];
- #ifdef DEBUG_PATTERNS
- printf("Note: %i ", buf[pos]);
- #endif
- pos++;
- }
- if (mask & 2) {
- j->Pattern[i].Note[numnotes].Instrument = buf[pos];
- j->Pattern[i].Note[numnotes].Mask |= 2;
- cinstrument[chn] = buf[pos];
- #ifdef DEBUG_PATTERNS
- printf("Inst: %i ", buf[pos]);
- #endif
- pos++;
- }
- if (mask & 4) {
- if (buf[pos] <= 64 || (buf[pos] >= 128 && buf[pos] <= 192))
- if (buf[pos] <= 64) {
- j->Pattern[i].Note[numnotes].Volume = buf[pos];
- j->Pattern[i].Note[numnotes].Mask |= 4;
- }
- else {
- j->Pattern[i].Note[numnotes].Panning = buf[pos] - 128;
- j->Pattern[i].Note[numnotes].Mask |= 8;
- }
- #ifdef DEBUG_PATTERNS
- printf("Vol: %i ", buf[pos]);
- #endif
- cvol[chn] = buf[pos];
- pos++;
- }
- if (mask & 8) {
- j->Pattern[i].Note[numnotes].Command = buf[pos];
- j->Pattern[i].Note[numnotes].CommandValue = buf[pos+1];
- j->Pattern[i].Note[numnotes].Mask |= 16;
- ccom[chn] = buf[pos];
- ccomval[chn] = buf[pos+1];
- #ifdef DEBUG_PATTERNS
- printf("Com: %i CommArg: %i ", buf[pos], buf[pos+1]);
- #endif
- pos+=2;
- }
- if (mask & 16) {
- j->Pattern[i].Note[numnotes].Note = cnote[chn];
- j->Pattern[i].Note[numnotes].Mask |= 1;
- #ifdef DEBUG_PATTERNS
- printf("LNote: %i ", cnote[chn]);
- #endif
- }
- if (mask & 32) {
- j->Pattern[i].Note[numnotes].Instrument = cinstrument[chn];
- j->Pattern[i].Note[numnotes].Mask |= 2;
- #ifdef DEBUG_PATTERNS
- printf("LInst: %i ", cinstrument[chn]);
- #endif
- }
- if (mask & 64) {
- if (cvol[chn] <= 64 || (cvol[chn] >= 128 && cvol[chn] <= 192))
- if (cvol[chn] <= 64) {
- j->Pattern[i].Note[numnotes].Volume = cvol[chn];
- j->Pattern[i].Note[numnotes].Mask |= 4;
- }
- else {
- j->Pattern[i].Note[numnotes].Panning = cvol[chn] - 128;
- j->Pattern[i].Note[numnotes].Mask |= 8;
- }
- #ifdef DEBUG_PATTERNS
- printf("LVol: %i ", cvol[chn]);
- #endif
- }
- if (mask & 128) {
- j->Pattern[i].Note[numnotes].Command = ccom[chn];
- j->Pattern[i].Note[numnotes].CommandValue = ccomval[chn];
- j->Pattern[i].Note[numnotes].Mask |= 16;
- #ifdef DEBUG_PATTERNS
- printf("LCom: %i LComArg: %i ", ccom[chn], ccomval[chn]);
- #endif
- }
- #ifdef DEBUG_PATTERNS
- printf("\n");
- #endif
- if (mask)
- numnotes++;
- #ifdef DEBUG_PATTERNS
- rest(1000);
- #endif
- }
- }
- if (insoffs)
- free(insoffs);
- if (samoffs)
- free(samoffs);
- if (patoffs)
- free(patoffs);
-
- return j;
-}
+#ifdef FORTIFY
+#include "fortify.h"
+#endif
+#include <stdio.h>
+#ifdef MSS
+#include "mss.h"
+#endif
+
+#include <string.h>
+
+#include "allegro.h"
+#include "modulus.h"
+#include "typedef.hpp"
+
+int detect_it(char *f) {
+ int sig;
+ PACKFILE *fn = pack_fopen(f, "rb");
+
+ if (fn == NULL)
+ return FALSE;
+
+ sig = pack_mgetl(fn);
+ if (sig != AL_ID('I','M','P','M')) {
+ pack_fclose(fn);
+ return FALSE;
+ }
+ pack_fclose(fn);
+
+ return TRUE;
+}
+
+MODULUS *create_it() {
+ MODULUS *m = (MODULUS*)malloc(sizeof(MODULUS));
+ if (!m)
+ return NULL;
+ memset(m, 0, sizeof(MODULUS));
+ return m;
+}
+
+void destroy_it(MODULUS *j) {
+
+ if (song->Music == j)
+ stop_it();
+
+ //remove patterns:
+ for (int i=0; i<j->NumPatterns; i++) {
+ free(j->Pattern[i].Note);
+ }
+ if (j->Pattern)
+ free(j->Pattern);
+ //remove instruments;
+ if (j->Instrument)
+ free(j->Instrument);
+ //remove samples;
+ for (int i=0; i<j->NumSamples; i++) {
+ destroy_sample(j->Sample[i].Sample);
+ }
+ if (j->Sample)
+ free(j->Sample);
+ //remove orders:
+ if (j->Order)
+ free(j->Order);
+ //remove channels:
+ for (int i=0; i<64; i++) {
+ if (j->Channel[i].VChannel) {
+ MODULUS_VCHANNEL *vchn = song->Music->Channel[i].VChannel;
+ MODULUS_VCHANNEL *prev = NULL;
+
+ if (!vchn)
+ continue;
+
+ for (;;) {
+ deallocate_voice(vchn->voice);
+
+ prev = vchn;
+ vchn = vchn->next;
+ free(prev);
+
+ if (!vchn)
+ break;
+ }
+ }
+ }
+ free(j);
+}
+
+//#define DEBUG_IT_SIZE
+
+int get_module_size(MODULUS *j) {
+ int a, b, c, d = 0, e;
+ a = sizeof(MODULUS) + j->NumOrders;
+ b = j->NumInstruments * sizeof(MODULUS_INSTRUMENT);
+ c = j->NumSamples * sizeof(MODULUS_SAMPLE);
+
+ for (int i=0; i<j->NumSamples; i++)
+ d += j->Sample[i].SampleLength * (j->Sample[i].Flag & 2 ? sizeof(short) : 1) * (j->Sample[i].Flag & 4 ? 2: 1);
+
+ e = 4 + sizeof(MODULUS_PATTERN) * j->NumPatterns;
+
+ for (int i=0; i<j->NumPatterns; i++)
+ e += j->Pattern[i].NumNotes * sizeof(MODULUS_NOTE);
+ #ifdef DEBUG_IT_SIZE
+ printf("Base: %i, Instruments(%i): %i, Samples(%i): %i, Data: %i, Patterns(%i): %i\n", a, j->NumInstruments, b, j->NumSamples, c, d, j->NumPatterns, e);
+ #endif
+
+ return a+b+c+d+e;
+}
+
+#define MAX_IT_CHN 64
+
+//#define DEBUG_HEADER
+//#define DEBUG_INSTRUMENTS
+//#define DEBUG_SAMPLES
+//#define DEBUG_PATTERNS
+
+static dword *sourcebuf = NULL;
+static dword *sourcepos = NULL;
+static byte rembits = 0;
+
+int readblock(PACKFILE *f) {
+ long size;
+ int c = pack_igetw(f);
+ if (c == -1)
+ return 0;
+ size = c;
+
+ sourcebuf = (dword*)malloc(size+4);
+ if (!sourcebuf)
+ return 0;
+
+ c = pack_fread(sourcebuf, size, f);
+ if (c < 1) {
+ free(sourcebuf);
+ sourcebuf = NULL;
+ return 0;
+ }
+ sourcepos = sourcebuf;
+ rembits = 32;
+ return 1;
+}
+
+void freeblock() {
+ if (sourcebuf)
+ free(sourcebuf);
+ sourcebuf = NULL;
+}
+
+dword readbits(char b) {
+ dword val;
+ if (b <= rembits) {
+ val = *sourcepos & ((1 << b) - 1);
+ *sourcepos >>= b;
+ rembits -= b;
+ }
+ else {
+ dword nbits = b - rembits;
+ val = *sourcepos;
+ sourcepos++;
+ val |= ((*sourcepos & ((1 << nbits) - 1)) << rembits);
+ *sourcepos >>= nbits;
+ rembits = 32 - nbits;
+ }
+ return val;
+}
+
+void decompress8(PACKFILE *f, void *data, int len, int tver) {
+ char *destbuf = (char*)data;
+ char *destpos = destbuf;
+ int blocklen, blockpos;
+ byte bitwidth;
+ word val;
+ char d1, d2;
+
+ memset(destbuf, 0, len);
+
+ while (len>0) {
+ //Read a block of compressed data:
+ if (!readblock(f))
+ return;
+ //Set up a few variables
+ blocklen = (len < 0x8000) ? len : 0x8000; //Max block length is 0x8000 bytes
+ blockpos = 0;
+ bitwidth = 9;
+ d1 = d2 = 0;
+ //Start the decompression:
+ while (blockpos < blocklen) {
+ //Read a value:
+ val = readbits(bitwidth);
+ //Check for bit width change:
+
+ if (bitwidth < 7) { //Method 1:
+ if (val == (1 << (bitwidth - 1))) {
+ val = readbits(3) + 1;
+ bitwidth = (val < bitwidth) ? val : val + 1;
+ continue;
+ }
+ }
+ else if (bitwidth < 9) { //Method 2
+ byte border = (0xFF >> (9 - bitwidth)) - 4;
+
+ if (val > border && val <= (border + 8)) {
+ val -= border;
+ bitwidth = (val < bitwidth) ? val : val + 1;
+ continue;
+ }
+ }
+ else if (bitwidth == 9) { //Method 3
+ if (val & 0x100) {
+ bitwidth = (val + 1) & 0xFF;
+ continue;
+ }
+ }
+ else { //Illegal width, abort ?
+ freeblock();
+ return;
+ }
+
+ //Expand the value to signed byte:
+ char v; //The sample value:
+ if (bitwidth < 8) {
+ byte shift = 8 - bitwidth;
+ v = (val << shift);
+ v >>= shift;
+ }
+ else
+ v = (char)val;
+
+ //And integrate the sample value
+ //(It always has to end with integration doesn't it ? ;-)
+ d1 += v;
+ d2 += d1;
+
+ //Store !
+ *destpos = ((tver == 0x215) ? d2 : d1);
+ destpos++;
+ blockpos++;
+ }
+ freeblock();
+ len -= blocklen;
+ }
+ return;
+}
+
+void decompress16(PACKFILE *f, void *data, int len, int tver) {
+ //make the output buffer:
+ short *destbuf = (short*)data;
+ short *destpos = destbuf;
+ int blocklen, blockpos;
+ byte bitwidth;
+ long val;
+ short d1, d2;
+
+ memset(destbuf, 0, len);
+
+ while (len>0) {
+ //Read a block of compressed data:
+ if (!readblock(f))
+ return;
+ //Set up a few variables
+ blocklen = (len < 0x4000) ? len : 0x4000; // Max block length is 0x4000 bytes
+ blockpos = 0;
+ bitwidth = 17;
+ d1 = d2 = 0;
+ //Start the decompression:
+ while (blockpos < blocklen) {
+ val = readbits(bitwidth);
+ //Check for bit width change:
+
+ if (bitwidth < 7) { //Method 1:
+ if (val == (1 << (bitwidth - 1))) {
+ val = readbits(4) + 1;
+ bitwidth = (val < bitwidth) ? val : val + 1;
+ continue;
+ }
+ }
+ else if (bitwidth < 17) { //Method 2
+ word border = (0xFFFF >> (17 - bitwidth)) - 8;
+
+ if (val > border && val <= (border + 16)) {
+ val -= border;
+ bitwidth = val < bitwidth ? val : val + 1;
+ continue;
+ }
+ }
+ else if (bitwidth == 17) { //Method 3
+ if (val & 0x10000) {
+ bitwidth = (val + 1) & 0xFF;
+ continue;
+ }
+ }
+ else { //Illegal width, abort ?
+ freeblock();
+ return;
+ }
+
+ //Expand the value to signed byte:
+ short v; //The sample value:
+ if (bitwidth < 16) {
+ byte shift = 16 - bitwidth;
+ v = (val << shift);
+ v >>= shift;
+ }
+ else
+ v = (short)val;
+
+ //And integrate the sample value
+ //(It always has to end with integration doesn't it ? ;-)
+ d1 += v;
+ d2 += d1;
+
+ //Store !
+ *destpos = ((tver == 0x215) ? d2 : d1);
+ destpos++;
+ blockpos++;
+ }
+ freeblock();
+ len -= blocklen;
+ }
+ return;
+}
+
+MODULUS *load_it(char *file) {
+ PACKFILE *f;
+ MODULUS *j = create_it();
+ int tver, tver2, flag, msglen, msgoffs;
+ int *insoffs = NULL, *samoffs = NULL, *patoffs = NULL;
+
+ if (!j)
+ return NULL;
+
+ if (!detect_it(file))
+ return NULL;
+
+ f = pack_fopen(file, "rb");
+
+ if (!f) {
+ #ifdef DEBUG_HEADER
+ printf("Error Opening!\n");
+ #endif
+ return NULL;
+ }
+
+ pack_fseek(f, 30);
+ pack_igetw(f); //I have no idea...
+
+ j->NumOrders = pack_igetw(f);
+ j->NumInstruments = pack_igetw(f);
+ j->NumSamples = pack_igetw(f);
+ j->NumPatterns = pack_igetw(f);
+
+ #ifdef DEBUG_HEADER
+ printf("Loading IT: %i Orders %i Instruments, %i Samples, %i Patterns\n", j->NumOrders, j->NumInstruments, j->NumSamples, j->NumPatterns);
+ #endif
+
+ tver = pack_igetw(f);
+ j->Version = tver2 = pack_igetw(f);
+
+ #ifdef DEBUG_HEADER
+ printf("Tracker ver: %X, %X\n", tver, tver2);
+ #endif
+
+ j->Flags = pack_igetw(f);
+ flag = pack_igetw(f);
+
+ j->GlobalVolume = pack_getc(f);
+ j->MixVolume = pack_getc(f);
+ j->Speed = pack_getc(f);
+ j->Tempo = pack_getc(f);
+ j->PanningSeperation = pack_getc(f);
+
+ #ifdef DEBUG_HEADER
+ printf("Global Volume: %i, Mixing Volume: %i, Speed: %i, Tempo: %i, PanSep: %i\n", j->GlobalVolume, j->MixVolume, j->Speed, j->Tempo, j->PanningSeperation);
+ #endif
+
+ pack_getc(f); //Damn....I need more info on this.
+
+ msglen = pack_igetw(f);
+ msgoffs = pack_igetl(f);
+
+ pack_fseek(f, 4);
+
+ #ifdef DEBUG_HEADER
+ printf("Channel Pan:");
+ #endif
+
+ for (int i=0; i<MAX_IT_CHN; i++) {
+ j->Channel[i].Pan = pack_getc(f);
+ #ifdef DEBUG_HEADER
+ printf(" %i", j->Channel[i].Pan);
+ #endif
+ }
+ #ifdef DEBUG_HEADER
+ printf("\nChannel Vol:");
+ #endif
+ for (int i=0; i<MAX_IT_CHN; i++) {
+ j->Channel[i].Volume = pack_getc(f);
+ #ifdef DEBUG_HEADER
+ printf(" %i", j->Channel[i].Volume);
+ #endif
+ }
+ #ifdef DEBUG_HEADER
+ printf("\n");
+ #endif
+
+ j->Order = (unsigned char *)malloc(j->NumOrders);
+ pack_fread(j->Order, j->NumOrders, f);
+
+ if (j->NumInstruments)
+ insoffs = (int*)malloc(4 * j->NumInstruments);
+ if (j->NumSamples)
+ samoffs = (int*)malloc(4 * j->NumSamples);
+ if (j->NumPatterns)
+ patoffs = (int*)malloc(4 * j->NumPatterns);
+
+ pack_fread(insoffs, 4 * j->NumInstruments, f);
+ pack_fread(samoffs, 4 * j->NumSamples, f);
+ pack_fread(patoffs, 4 * j->NumPatterns, f);
+
+ if (flag&1) { //Song message attached
+ //Ignore.
+ }
+ if (flag & 4) { //skip something:
+ short u;
+ char dummy[8];
+ u = pack_igetw(f);
+ for (int i=0; i<u; u++)
+ pack_fread(dummy, 8, f);
+ }
+ if (flag & 8) { //MIDI commands ???
+ char dummy[33];
+ for (int i=0; i<9+16+128; i++)
+ pack_fread(dummy, 32, f);
+
+ }
+
+ if (j->NumInstruments)
+ j->Instrument = (MODULUS_INSTRUMENT*)malloc(sizeof(MODULUS_INSTRUMENT) * j->NumInstruments);
+ #ifdef DEBUG_INSTRUMENTS
+ if (!j->Instrument)
+ printf("No Mem for Instruments!\n");
+ #endif
+
+
+ for (int i=0; i<j->NumInstruments; i++) {
+ pack_fclose(f);
+ f = pack_fopen(file, "rb");
+ #ifdef DEBUG_INSTRUMENTS
+ if (!f)
+ printf("Error Opening!\n");
+ #endif
+ pack_fseek(f, insoffs[i] + 17);
+
+ j->Instrument[i].NewNoteAction = pack_getc(f);
+ j->Instrument[i].DuplicateCheckType = pack_getc(f);
+ j->Instrument[i].DuplicateCheckAction = pack_getc(f);
+ j->Instrument[i].FadeOut = pack_igetw(f);
+ j->Instrument[i].PitchPanSeperation = pack_getc(f);
+ j->Instrument[i].PitchPanCenter = pack_getc(f);
+ j->Instrument[i].GlobalVolume = pack_getc(f);
+ j->Instrument[i].DefaultPan = pack_getc(f);
+ #ifdef DEBUG_INSTRUMENTS
+ printf("I%02i @ 0x%X, NNA %i, DCT %i, DCA %i, FO %i, PPS %i, PPC %i, GVol %i, DPan %i\n", i, insoffs[i], j->Instrument[i].NewNoteAction, j->Instrument[i].DuplicateCheckType, j->Instrument[i].DuplicateCheckAction, j->Instrument[i].FadeOut, j->Instrument[i].PitchPanSeperation, j->Instrument[i].PitchPanCenter, j->Instrument[i].GlobalVolume, j->Instrument[i].DefaultPan);
+ #endif
+
+ pack_fseek(f, 38);
+
+ for (int k=0; k<120; k++) {
+ j->Instrument[i].NoteNote[k] = pack_getc(f);
+ j->Instrument[i].NoteSample[k] = pack_getc(f) - 1;
+ }
+
+ j->Instrument[i].VolumeEnvelope.Flag = pack_getc(f);
+ j->Instrument[i].VolumeEnvelope.NumNodes = pack_getc(f);
+ j->Instrument[i].VolumeEnvelope.LoopBegin = pack_getc(f);
+ j->Instrument[i].VolumeEnvelope.LoopEnd = pack_getc(f);
+ j->Instrument[i].VolumeEnvelope.SustainLoopBegin = pack_getc(f);
+ j->Instrument[i].VolumeEnvelope.SustainLoopEnd = pack_getc(f);
+ for (int k=0; k<j->Instrument[i].VolumeEnvelope.NumNodes; k++) {
+ j->Instrument[i].VolumeEnvelope.NodeY[k] = pack_getc(f);
+ j->Instrument[i].VolumeEnvelope.NodeTick[k] = pack_igetw(f);
+ }
+ pack_fseek(f, 75 - j->Instrument[i].VolumeEnvelope.NumNodes * 3);
+
+ j->Instrument[i].PanningEnvelope.Flag = pack_getc(f);
+ j->Instrument[i].PanningEnvelope.NumNodes = pack_getc(f);
+ j->Instrument[i].PanningEnvelope.LoopBegin = pack_getc(f);
+ j->Instrument[i].PanningEnvelope.LoopEnd = pack_getc(f);
+ j->Instrument[i].PanningEnvelope.SustainLoopBegin = pack_getc(f);
+ j->Instrument[i].PanningEnvelope.SustainLoopEnd = pack_getc(f);
+ for (int k=0; k<j->Instrument[i].PanningEnvelope.NumNodes; k++) {
+ j->Instrument[i].PanningEnvelope.NodeY[k] = pack_getc(f);
+ j->Instrument[i].PanningEnvelope.NodeTick[k] = pack_igetw(f);
+ }
+ pack_fseek(f, 75 - j->Instrument[i].PanningEnvelope.NumNodes * 3);
+
+ j->Instrument[i].PitchEnvelope.Flag = pack_getc(f);
+ j->Instrument[i].PitchEnvelope.NumNodes = pack_getc(f);
+ j->Instrument[i].PitchEnvelope.LoopBegin = pack_getc(f);
+ j->Instrument[i].PitchEnvelope.LoopEnd = pack_getc(f);
+ j->Instrument[i].PitchEnvelope.SustainLoopBegin = pack_getc(f);
+ j->Instrument[i].PitchEnvelope.SustainLoopEnd = pack_getc(f);
+ for (int k=0; k<j->Instrument[i].PitchEnvelope.NumNodes; k++) {
+ j->Instrument[i].PitchEnvelope.NodeY[k] = pack_getc(f);
+ j->Instrument[i].PitchEnvelope.NodeTick[k] = pack_igetw(f);
+ }
+ }
+
+ if (j->NumSamples)
+ j->Sample = (MODULUS_SAMPLE*)malloc(sizeof(MODULUS_SAMPLE) * j->NumSamples);
+
+ #ifdef DEBUG_SAMPLES
+ if (!j->Sample)
+ printf("No Mem for Samples!\n");
+ #endif
+
+ for (int i=0; i<j->NumSamples; i++) {
+ int sam_samptr, convert;
+
+ pack_fclose(f);
+ f = pack_fopen(file, "rb");
+ #ifdef DEBUG_SAMPLES
+ if (!f)
+ printf("Error opening!\n");
+ #endif
+
+ pack_fseek(f, samoffs[i] + 17);
+
+ j->Sample[i].GlobalVolume = pack_getc(f);
+ j->Sample[i].Flag = pack_getc(f);
+ j->Sample[i].Volume = pack_getc(f);
+
+ #ifdef DEBUG_SAMPLES
+ printf("S%02i @ 0x%X, Vol: %i/%i, Flag: %i", i, samoffs[i], j->Sample[i].GlobalVolume, j->Sample[i].Volume, j->Sample[i].Flag);
+ #endif
+
+ pack_fseek(f, 26);
+
+ convert = pack_getc(f);
+ pack_getc(f); //Panning ?
+
+ j->Sample[i].SampleLength = pack_igetl(f);
+ j->Sample[i].LoopBegin = pack_igetl(f);
+ j->Sample[i].LoopEnd = pack_igetl(f);
+ j->Sample[i].C5Speed = pack_igetl(f);
+ j->Sample[i].SustainLoopBegin = pack_igetl(f);
+ j->Sample[i].SustainLoopEnd = pack_igetl(f);
+
+ #ifdef DEBUG_SAMPLES
+ printf(", SLen: %i, LpB: %i, LpE: %i, C5S: %i\n", j->Sample[i].SampleLength, j->Sample[i].LoopBegin, j->Sample[i].LoopEnd, j->Sample[i].C5Speed);
+ #endif
+
+ sam_samptr = pack_igetl(f);
+
+ j->Sample[i].VibratoSpeed = pack_getc(f);
+ j->Sample[i].VibratoDepth = pack_getc(f);
+ j->Sample[i].VibratoRate = pack_getc(f);
+ j->Sample[i].VibratoWaveForm = pack_getc(f);
+
+ #ifdef DEBUG_SAMPLES
+ printf("SusLpB: %i, SusLpE: %i, VibSp: %i, VibDep: %i, VibWav: %i, VibRat: %i\n", j->Sample[i].SustainLoopBegin, j->Sample[i].SustainLoopEnd, j->Sample[i].VibratoSpeed, j->Sample[i].VibratoDepth, j->Sample[i].VibratoWaveForm, j->Sample[i].VibratoRate);
+ #endif
+
+ if (j->Sample[i].Flag & 1 == 0)
+ continue;
+
+ pack_fclose(f);
+ f = pack_fopen(file, "rb");
+ pack_fseek(f, sam_samptr);
+
+ int len = j->Sample[i].SampleLength * (j->Sample[i].Flag & 2 ? sizeof(short) : 1) * (j->Sample[i].Flag & 4 ? 2: 1);
+
+ #ifdef DEBUG_SAMPLES
+ printf("Len: %i, Size: %i KB\n", j->Sample[i].SampleLength, len/1024);
+ #endif
+
+ SAMPLE *sam = create_sample(j->Sample[i].Flag & 2 ? 16 : 8, j->Sample[i].Flag & 4 ? TRUE : FALSE, j->Sample[i].C5Speed, j->Sample[i].SampleLength);
+
+ if (j->Sample[i].Flag & 8) { // If the sample is packed, then we must unpack it
+ if (j->Sample[i].Flag & 2)
+ decompress16(f, sam->data, j->Sample[i].SampleLength, tver2);
+ else
+ decompress8(f, sam->data, j->Sample[i].SampleLength, tver2);
+ } else {
+ pack_fread(sam->data, len, f);
+ }
+
+ if (j->Sample[i].Flag & SAMPLE_USELOOP) {
+ sam->loop_start = j->Sample[i].LoopBegin;
+ sam->loop_end = j->Sample[i].LoopEnd;
+ }
+
+ j->Sample[i].Sample = sam;
+
+ void *dat = sam->data;
+
+ if (convert & 2) { //Change the byte order for 16-bit samples:
+ if (sam->bits == 16) {
+ for (int k=0; k<len; k+=2) {
+ int l = ((char*)dat)[k];
+ ((char*)dat)[k] = ((char*)dat)[k+1];
+ ((char*)dat)[k+1] = l;
+
+ }
+ }
+ else {
+ for (int k=0; k<len; k+=2) {
+ int l = ((char*)dat)[k];
+ ((char*)dat)[k] = ((char*)dat)[k+1];
+ ((char*)dat)[k+1] = l;
+
+ }
+ }
+ }
+ if (convert & 1) { //Convert to unsigned
+ if (sam->bits == 8) {
+ for (int k=0; k<len; k++) {
+ ((char*)dat)[k] ^= 0x80;
+ }
+ }
+ else {
+ for (int k=0; k<(len>>1); k++) {
+ ((short*)dat)[k] ^= 0x8000;
+ }
+ }
+ }
+ }
+
+ if (j->NumPatterns)
+ j->Pattern = (MODULUS_PATTERN*)malloc(sizeof(MODULUS_PATTERN) * j->NumPatterns);
+ unsigned char *buf = (unsigned char*)alloca(65536);
+ unsigned char *cmask = (unsigned char*)alloca(64),
+ *cnote = (unsigned char*)alloca(64),
+ *cinstrument = (unsigned char*)alloca(64),
+ *cvol = (unsigned char*)alloca(64),
+ *ccom = (unsigned char*)alloca(64),
+ *ccomval = (unsigned char*)alloca(64);
+
+ for (int i=0; i<j->NumPatterns; i++) {
+ int numnotes = 0, len, pos = 0, mask = 0, chn = 0;
+
+ memset(cmask, 0, 64);
+ memset(cnote, 0, 64);
+ memset(cinstrument, 0, 64);
+ memset(cvol, 0, 64);
+ memset(ccom, 0, 64);
+ memset(ccomval, 0, 64);
+
+ pack_fclose(f);
+ f = pack_fopen(file, "rb");
+ pack_fseek(f, patoffs[i]);
+
+ len = pack_igetw(f);
+ j->Pattern[i].NumRows = pack_igetw(f);
+
+ pack_fseek(f, 4);
+ pack_fread(buf, len, f);
+
+ while (pos < len) {
+ int b = buf[pos];
+ pos++;
+ if (!b) { //If end of row:
+ numnotes++;
+ continue;
+ }
+ chn = (b - 1) & 63;
+
+ if (b & 128) {
+ mask = buf[pos];
+ pos++;
+ cmask[chn] = mask;
+ }
+ else
+ mask = cmask[chn];
+
+ if (mask)
+ numnotes++;
+ if (mask & 1)
+ pos++;
+ if (mask & 2)
+ pos++;
+ if (mask & 4)
+ pos++;
+ if (mask & 8)
+ pos+=2; //Guessing here
+ }
+ j->Pattern[i].NumNotes = numnotes;
+ j->Pattern[i].Note = (MODULUS_NOTE*)malloc(sizeof(MODULUS_NOTE) * numnotes);
+ memset(j->Pattern[i].Note, 0, sizeof(MODULUS_NOTE) * numnotes);
+
+ pos = 0;
+ memset(cmask, 0, 64);
+ mask = 0;
+ numnotes = 0;
+ while (pos < len) {
+ int b = buf[pos];
+ #ifdef DEBUG_PATTERNS
+ printf("NumNote: %i ", numnotes);
+ #endif
+
+ pos++;
+ if (!b) { //If end of row:
+ j->Pattern[i].Note[numnotes].Channel = -1;
+ numnotes++;
+ #ifdef DEBUG_PATTERNS
+ printf("Channel: -1\n");
+ #endif
+ continue;
+ }
+ chn = (b - 1) & 63;
+
+ if (b & 128) {
+ mask = buf[pos];
+ pos++;
+ cmask[chn] = mask;
+ }
+ else
+ mask = cmask[chn];
+ #ifdef DEBUG_PATTERNS
+ printf("Channel: %i Mask: %i ", chn, mask);
+ #endif
+
+ if (mask)
+ j->Pattern[i].Note[numnotes].Channel = chn;
+
+ if (mask & 1) {
+ j->Pattern[i].Note[numnotes].Note = buf[pos];
+ j->Pattern[i].Note[numnotes].Mask |= 1;
+ cnote[chn] = buf[pos];
+ #ifdef DEBUG_PATTERNS
+ printf("Note: %i ", buf[pos]);
+ #endif
+ pos++;
+ }
+ if (mask & 2) {
+ j->Pattern[i].Note[numnotes].Instrument = buf[pos];
+ j->Pattern[i].Note[numnotes].Mask |= 2;
+ cinstrument[chn] = buf[pos];
+ #ifdef DEBUG_PATTERNS
+ printf("Inst: %i ", buf[pos]);
+ #endif
+ pos++;
+ }
+ if (mask & 4) {
+ if (buf[pos] <= 64 || (buf[pos] >= 128 && buf[pos] <= 192))
+ if (buf[pos] <= 64) {
+ j->Pattern[i].Note[numnotes].Volume = buf[pos];
+ j->Pattern[i].Note[numnotes].Mask |= 4;
+ }
+ else {
+ j->Pattern[i].Note[numnotes].Panning = buf[pos] - 128;
+ j->Pattern[i].Note[numnotes].Mask |= 8;
+ }
+ #ifdef DEBUG_PATTERNS
+ printf("Vol: %i ", buf[pos]);
+ #endif
+ cvol[chn] = buf[pos];
+ pos++;
+ }
+ if (mask & 8) {
+ j->Pattern[i].Note[numnotes].Command = buf[pos];
+ j->Pattern[i].Note[numnotes].CommandValue = buf[pos+1];
+ j->Pattern[i].Note[numnotes].Mask |= 16;
+ ccom[chn] = buf[pos];
+ ccomval[chn] = buf[pos+1];
+ #ifdef DEBUG_PATTERNS
+ printf("Com: %i CommArg: %i ", buf[pos], buf[pos+1]);
+ #endif
+ pos+=2;
+ }
+ if (mask & 16) {
+ j->Pattern[i].Note[numnotes].Note = cnote[chn];
+ j->Pattern[i].Note[numnotes].Mask |= 1;
+ #ifdef DEBUG_PATTERNS
+ printf("LNote: %i ", cnote[chn]);
+ #endif
+ }
+ if (mask & 32) {
+ j->Pattern[i].Note[numnotes].Instrument = cinstrument[chn];
+ j->Pattern[i].Note[numnotes].Mask |= 2;
+ #ifdef DEBUG_PATTERNS
+ printf("LInst: %i ", cinstrument[chn]);
+ #endif
+ }
+ if (mask & 64) {
+ if (cvol[chn] <= 64 || (cvol[chn] >= 128 && cvol[chn] <= 192))
+ if (cvol[chn] <= 64) {
+ j->Pattern[i].Note[numnotes].Volume = cvol[chn];
+ j->Pattern[i].Note[numnotes].Mask |= 4;
+ }
+ else {
+ j->Pattern[i].Note[numnotes].Panning = cvol[chn] - 128;
+ j->Pattern[i].Note[numnotes].Mask |= 8;
+ }
+ #ifdef DEBUG_PATTERNS
+ printf("LVol: %i ", cvol[chn]);
+ #endif
+ }
+ if (mask & 128) {
+ j->Pattern[i].Note[numnotes].Command = ccom[chn];
+ j->Pattern[i].Note[numnotes].CommandValue = ccomval[chn];
+ j->Pattern[i].Note[numnotes].Mask |= 16;
+ #ifdef DEBUG_PATTERNS
+ printf("LCom: %i LComArg: %i ", ccom[chn], ccomval[chn]);
+ #endif
+ }
+ #ifdef DEBUG_PATTERNS
+ printf("\n");
+ #endif
+ if (mask)
+ numnotes++;
+ #ifdef DEBUG_PATTERNS
+ rest(1000);
+ #endif
+ }
+ }
+ if (insoffs)
+ free(insoffs);
+ if (samoffs)
+ free(samoffs);
+ if (patoffs)
+ free(patoffs);
+
+ return j;
+}