#include"mod.h" MOD*mod_open(const char*fn) { FILE*file; MOD*mod; size_t highest_pattern; // Open file file=fopen(fn,"r"); if(!file) { printf("error: failed to open '%s'\n",fn); return NULL; } // Allocate internal mod mod=malloc(sizeof(MOD)); // Read file fread(mod,154+NUMBER_OF_SAMPLES*sizeof(MODSAMPLE),1,file); for(size_t i=0;isample_data[i]=NULL; // Initialize pointers to NULL // Get highest_pattern highest_pattern=mod_gethighestpattern(mod); // Allocate, read in pattern data for(size_t i=0;ipatterns[i]=(MODPATTERN*)malloc(sizeof(MODPATTERN)); if(!mod->patterns[i]) { printf("error: failed to allocate memory for pattern #%02x\n", (uint32_t)i); mod_delete(mod); return NULL; } fread(mod->patterns[i],1,sizeof(MODPATTERN),file); } // Allocate, read in sample data for(size_t i=0;i<31;++i) { size_t samplelength=bswap_16(mod->samples[i].samplelength)*sizeof(int16_t); if(samplelength>1) { // Allocate memory, verify mod->sample_data[i]=(uint16_t*)malloc(samplelength); if(!mod->sample_data[i]) { printf("error: failed to allocate memory for sample #%02x (length: %lu)\n", (uint32_t)i, (size_t)samplelength); mod_delete(mod); return NULL; } // Read sample into new memory fread(mod->sample_data[i],1,samplelength,file); } else mod->sample_data[i]=NULL; } // Done fclose(file); // Return return mod; } void mod_print(MOD*mod) { int highest_pattern; // PRINT DATA ----- // Overlay MOD mod struct, print data printf("Mod name: '%.20s'\n",mod->name); // Samples printf("Sample\tName\t\t\t\tLength\tFine\tVolume\tStart\tRepeat\n"); for(int i=0,drawbar=1;isamples[i].volume==0||mod->samples[i].samplelength<2) { drawbar&&puts("--------"),drawbar=0; // Draw one bar until next non-empty sample continue; } printf("%02x\t",i+1); printf("'%22.22s'\t",mod->samples[i].name); printf("% 6d\t",bswap_16(mod->samples[i].samplelength)*2); printf("% 6d\t",bswap_16(mod->samples[i].finetune)); printf("% 6d\t",(mod->samples[i].volume)); printf("% 6d\t",bswap_16(mod->samples[i].repeatstart)); printf("% 6d",bswap_16(mod->samples[i].repeatlength)); puts(""); drawbar=1; // Draw a visual bar next 'empty' sample } printf("Number song positions: %d\n",mod->positions); printf("MOD file type: '%.4s'\n",mod->magic); // Pattern table puts("Pattern Table:"); highest_pattern=mod->patterntable[0]; for(int i=0,inc=24;i<128&&ipositions;i+=inc) { for(int j=0;jpositions);++j) { printf("%02x ",mod->patterntable[i+j]); // Find highest pattern number (therefore the // # of patterns that are stored) if(mod->patterntable[i+j]>highest_pattern) highest_pattern=mod->patterntable[i+j]; } puts(""); } printf("Number of patterns: %d (highest: %02x)\n",highest_pattern+1,highest_pattern); // DONE PRINTING DATA ----- } void mod_printpatterns(MOD*mod) { size_t highest_pattern=mod_gethighestpattern(mod); // Print pattern/channel data puts("\nPattern data:"); for(size_t i=0;i<=highest_pattern;++i) { // Display pattern number printf("Pattern %02lx:\n",i); for(size_t k=0;k<4;++k) { printf("fq sm fx"); if(k<3) printf(" "); } puts(""); // Print channel data for each division j of pattern i for(size_t j=0;j<4*64;) { // Print period, sample, and effect for this row for each channel for(size_t k=0;k<4;++k) { uint32_t data=bswap_32(mod->patterns[i]->channel_data[j+k]); //printf("%.3u %02x %03x", printf("%s %02x %03x", mod_getnotename((data&0x0fff0000)>>16), //(data&0x0fff0000)>>16, (((data&0xf0000000)>>12)>>12|(data&0xf000)>>12), data&0xfff //data ); if(k<3)printf(" | "); } j+=4; puts(""); } } } size_t mod_gethighestpattern(MOD*mod) { size_t highest_pattern; // Get highest_pattern highest_pattern=mod->patterntable[0]; for(size_t i=0;ipositions;++i) if(highest_patternpatterntable[i]) highest_pattern=mod->patterntable[i]; return highest_pattern; } void mod_delete(MOD*mod) { size_t highest_pattern; if(!mod)return; // Get highest_pattern highest_pattern=mod->patterntable[0]; for(size_t i=0;ipositions;++i) if(highest_patternpatterntable[i]) highest_pattern=mod->patterntable[i]; // Delete patterns for(size_t i=0;ipatterns[i]) free(mod->patterns[i]); // Delete samples for(size_t i=0;i<31;++i) if(mod->sample_data[i]) free(mod->sample_data[i]); free(mod); } char*mod_getnotename(uint16_t note) { static uint16_t periods[]={ //C C# D D# E F F# G G# A A# B 1712,1616,1525,1440,1357,1281,1209,1141,1077,1017, 961, 907, //0 856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453, //1 428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226, //2 214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120, 113, //3 107, 101, 95, 90, 85, 80, 76, 71, 67, 64, 60, 57, //4 }; static char*names[]={"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"}; static char name[16]; int which=-1; if(note==0)return "---"; // Find which one for(int i=0;i