Just some notes and SPEC stuff.
[pineappletracker.git] / mod / main.c
blobb5c02cba436966bcb9e61882d311174da0579347
1 #include <stdio.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <string.h>
6 #define MOD_NO_NOTE 63
7 #define MOD_NO_SAMPLE 31
9 typedef uint8_t u8;
10 typedef uint16_t u16;
11 typedef uint32_t u32;
13 typedef int8_t s8;
14 typedef int16_t s16;
15 typedef int32_t s32;
17 static char *notenames[] = {"C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-",
18 "G#", "A-", "A#", "H-"};
20 struct sample_header {
21 u8 name[22]; //22 bytes
22 u16 length; //2 bytes
23 u8 finetune; //1 byte
24 u8 vol; //1 byte
25 u16 loopstart; //2 bytes
26 u16 looplength; //2 bytes
27 signed char *smpdata; //1 byte
30 struct pattern_entry {
31 u16 period;
32 u8 sample;
33 u8 effect;
34 u8 param;
37 struct pattern {
38 struct pattern_entry pattern_entry[64][4];
41 struct mod_header {
42 char name[20];
43 struct sample_header sample[31];
44 u8 order[128];
45 //u8 **pattern;
46 struct pattern *patterns;
47 u8 orderCount;
48 u8 patternCount;
51 int main(int argc, char **argv){
52 FILE *modfile;
53 struct mod_header modheader;
54 int i;
55 int trash;
56 u8 highestPattern = 0;
58 const u16 octave1Period[12] = {
59 856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453
62 u16 periodTable[12*5];
63 u8 octave,note;
64 char sig[4];
66 for(octave = 0; octave < 5; octave++){
67 for(note = 0; note < 12; note++){
68 //*2 to get us into octave 0, then divide by 2 for each
69 // octave from there
70 periodTable[octave*12 + note] =
71 (octave1Period[note]*2) >> octave;
75 /* ~opening the modfile~ */
76 modfile = fopen(argv[1], "rb");
78 if(!modfile){
79 printf("Couldn't open file!\n");
80 return 1;
83 /* ~is it a mod?~ */
84 // probably unnecessary
85 /*fseek(modfile, 1080, SEEK_SET);
86 fread(&sig, 1, 4, modfile);
87 if(strcmp(sig,"M.K.")){
88 printf("not a MOD\n");
89 printf(sig);
90 exit(1);
91 }else{
92 printf("YES");
93 }*/
95 /* ~what's its name?~ */
96 rewind(modfile);
97 fread(modheader.name, 20, 1, modfile);
98 modheader.name[19] = '\0';
100 /* ~ load samples ~*/
101 for(i = 0; i < 31; i++){
102 fread(&modheader.sample[i], 30, 1, modfile);
103 modheader.sample[i].smpdata = NULL;
105 modheader.sample[i].length =
106 ( ((modheader.sample[i].length & 0xff) << 8) |
107 (modheader.sample[i].length >> 8) );
109 modheader.sample[i].loopstart =
110 ( ((modheader.sample[i].loopstart & 0xff) << 8) |
111 (modheader.sample[i].loopstart >> 8) );
113 modheader.sample[i].looplength =
114 ( ((modheader.sample[i].looplength & 0xff) << 8) |
115 (modheader.sample[i].looplength >> 8) );
118 /*~ load orders ~*/
119 fread(&modheader.orderCount, 1, 1, modfile);
121 fread(&trash, 1, 1, modfile); //useless byte
123 fread(&modheader.order, 128, 1 , modfile);
125 /*~ load patterns ~*/
126 for(i = 0; i < modheader.orderCount; i++){
127 if(modheader.order[i] > highestPattern)
128 highestPattern = modheader.order[i];
131 modheader.patternCount = highestPattern + 1;
133 // allocate space for patterns
134 modheader.patterns = malloc(sizeof(struct pattern[modheader.patternCount]));
136 if(modheader.patterns==NULL){
137 printf("out of memory!\n");
138 exit(1);
142 //initialize modheader.pattern to 0
143 /* XXX SEGFAULT */
144 //memset(modheader.pattern, 0, modheader.patternCount*sizeof(u8*));
146 u8 curPattern, row, column;
148 for(curPattern = 0; curPattern < modheader.patternCount; curPattern++){
149 //modheader.patterns[curPattern] = malloc(1024); //patterns are always 1k
150 /*modheader.patterns[curPattern] = malloc(sizeof(struct pattern));
151 if(!modheader.patterns[curPattern]){
152 printf("out of memory!\n");
155 //initialize to 0
156 memset(modheader.patterns[curPattern], 0, 1024);
159 for(row = 0; row < 64; row++){
160 for(column = 0; column < 4; column++){
161 u8 cell[4];
162 u8 sample;
163 u16 period;
164 u8 effect;
165 u8 param;
167 fread(cell, 4, 1, modfile);
169 sample = (cell[0] & 0xf0) | (cell[2] >> 4);
170 period = cell[1] | ((cell[0] & 0xf) << 8);
171 effect = cell[2] & 0xf;
172 param = cell[3];
174 //looping through the period table
175 /*u8 closestNote = 0;
176 u16 closestDist = 0xffff; //make sure the first comparison sets the closet note
177 u16 newDist;
180 if(period == 0){
181 period = MOD_NO_NOTE; //period 0 is no note
184 /*else {
185 for(i = 0; i < 12*5; i++){
186 newDist = abs(period = periodTable[i]);
187 if(newDist < closestDist){
188 closestNote = i;
189 closestDist = newDist;
195 if(sample == 0){
196 sample = MOD_NO_SAMPLE;
197 }else {
198 sample -= 1;
201 //now that we have our note, we can store the data in our new pattern
202 //calculate the address of the cell to output to
203 // rowoffset = row * 4 columns per row * 4 bytes per cell
204 // columnoffset = column * 4 bytes per cell
206 /*u8 *outCell = &modheader.pattern[curPattern][row*4*4 + column*4];
207 outCell[0] = closestNote;
208 outCell[1] = sample;
209 outCell[2] = effect;
210 outCell[3] = param;
212 modheader.patterns[curPattern].pattern_entry[row][column].period = period;
213 modheader.patterns[curPattern].pattern_entry[row][column].sample = sample;
214 modheader.patterns[curPattern].pattern_entry[row][column].effect = effect;
215 modheader.patterns[curPattern].pattern_entry[row][column].param = param;
221 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
222 //done reading modfile
223 fclose(modfile);
225 printf("%s\n", modheader.name);
227 for(i = 0; i < 31; i++) {
228 printf("%i: %s\n", i, modheader.sample[i].name);
229 printf("%i: length:%i\n", i, modheader.sample[i].length);
232 printf("highest pattern: %i\n", highestPattern);
234 printf("orderCount: %i\n", modheader.orderCount);
236 printf("patternCount: %i\n", modheader.patternCount);
238 //printf("%i\n", sizeof(u8*[modheader.patternCount])); //36
239 //printf("%i\n", sizeof(u8*)); //4
241 /*for(i = 0; i < modheader.patternCount+1; i++)
242 for(row = 0; row < 64; row++)
243 printf("%i\n", modheader.pattern[i][row]);
246 for(i = 0; i < modheader.orderCount; i++)
247 printf("%i : %i\n", i, modheader.order[i]);
249 for(row = 0; row < 64; row++){
250 printf("%i %x %x %x\n", modheader.patterns[7].pattern_entry[row][0].period,
251 modheader.patterns[7].pattern_entry[row][0].sample + 1,
252 modheader.patterns[7].pattern_entry[row][0].effect,
253 modheader.patterns[7].pattern_entry[row][0].param);
256 return 0;