git ssb

0+

kode54 / syntrax-c



Tree: 7546e2f74d2ea029c47a53149da67f11f39cb16a

Files: 7546e2f74d2ea029c47a53149da67f11f39cb16a / src / syntrax / file.c

13104 bytesRaw
1#include <stdint.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5
6#include "file.h"
7
8size_t filesize;
9
10Song* File_loadSong(const char *path)
11{
12 Song *synSong;
13 FILE *f;
14 uint8_t *buffer;
15 size_t size;
16
17 if (!(f = fopen(path, "rb"))) return NULL;
18
19 fseek(f, 0, SEEK_END);
20 size = ftell(f);
21 fseek(f, 0, SEEK_SET);
22
23 if (!(buffer = (uint8_t *) malloc(size))) {
24 fclose(f);
25 return NULL;
26 }
27
28 if (fread(buffer, 1, size, f) != size) {
29 free(buffer);
30 fclose(f);
31 return NULL;
32 }
33
34 fclose(f);
35
36 synSong = File_loadSongMem(buffer, size);
37
38 free(buffer);
39
40 return synSong;
41}
42
43uint16_t get_le16(const void *p)
44{
45 return (((const uint8_t*)p)[0]) +
46 (((const uint8_t*)p)[1]) * 0x100;
47}
48
49uint32_t get_le32(const void *p)
50{
51 return (((const uint8_t*)p)[0]) +
52 (((const uint8_t*)p)[1]) * 0x100 +
53 (((const uint8_t*)p)[2]) * 0x10000 +
54 (((const uint8_t*)p)[3]) * 0x1000000;
55}
56
57static long File_readHeader(SongHeader *h, const uint8_t *buffer, size_t size)
58{
59 if (size < 52) return -1;
60
61 h->version = get_le16(buffer);
62 h->UNK00 = get_le16(buffer + 2);
63 h->patNum = get_le32(buffer + 4);
64 h->subsongNum = get_le32(buffer + 8);
65 h->instrNum = get_le32(buffer + 12);
66 h->UNK01 = get_le32(buffer + 16);
67 h->UNK02 = get_le16(buffer + 20);
68 h->UNK03 = get_le16(buffer + 22);
69 h->UNK04 = get_le16(buffer + 24);
70 h->UNK05 = get_le16(buffer + 26);
71 h->UNK06 = get_le16(buffer + 28);
72 h->UNK07 = get_le16(buffer + 30);
73 h->UNK08 = get_le16(buffer + 32);
74 h->UNK09 = get_le16(buffer + 34);
75 h->UNK0A = get_le16(buffer + 36);
76 h->UNK0B = get_le16(buffer + 38);
77 h->UNK0C = get_le16(buffer + 40);
78 h->UNK0D = get_le16(buffer + 42);
79 h->UNK0E = get_le16(buffer + 44);
80 h->UNK0F = get_le16(buffer + 46);
81 h->UNK10 = get_le16(buffer + 48);
82 h->UNK11 = get_le16(buffer + 50);
83
84 return 52;
85}
86
87static long File_readSubSong(Subsong *subSong, const uint8_t *buffer, size_t size)
88{
89 int i, j;
90
91 if (size < 16564) return -1;
92
93 for (i = 0; i < 16; i++)
94 subSong->UNK00[i] = get_le32(buffer + i * 4);
95
96 for (i = 0; i < SE_MAXCHANS; i++)
97 subSong->mutedChans[i] = buffer[64 + i];
98
99 subSong->tempo = get_le32(buffer + 80);
100 subSong->groove = get_le32(buffer + 84);
101 subSong->startPosCoarse = get_le32(buffer + 88);
102 subSong->startPosFine = get_le32(buffer + 92);
103 subSong->endPosCoarse = get_le32(buffer + 96);
104 subSong->endPosFine = get_le32(buffer + 100);
105 subSong->loopPosCoarse = get_le32(buffer + 104);
106 subSong->loopPosFine = get_le32(buffer + 108);
107 subSong->isLooping = get_le16(buffer + 112);
108
109 memcpy(subSong->m_Name, buffer + 114, 32);
110 subSong->m_Name[32] = '\0';
111
112 subSong->channelNumber = get_le16(buffer + 146);
113 subSong->delayTime = get_le16(buffer + 148);
114
115 for (i = 0; i < SE_MAXCHANS; i++)
116 subSong->chanDelayAmt[i] = buffer[150 + i];
117
118 subSong->amplification = get_le16(buffer + 166);
119
120 subSong->UNK01 = get_le16(buffer + 168);
121 subSong->UNK02 = get_le16(buffer + 170);
122 subSong->UNK03 = get_le16(buffer + 172);
123 subSong->UNK04 = get_le16(buffer + 174);
124 subSong->UNK05 = get_le16(buffer + 176);
125 subSong->UNK06 = get_le16(buffer + 178);
126
127 for (i = 0; i < SE_MAXCHANS; i++) {
128 for (j = 0; j < 0x100; j++) {
129 subSong->orders[i][j].patIndex = get_le16(buffer + 180 + i * 1024 + j * 4);
130 subSong->orders[i][j].patLen = get_le16(buffer + 180 + i * 1024 + j * 4 + 2);
131 }
132 }
133
134 return 16564;
135}
136
137long File_readRow(Row *r, const uint8_t *buffer, size_t size)
138{
139 if (size < 5) return -1;
140
141 r->note = buffer[0];
142 r->dest = buffer[1];
143 r->instr = buffer[2];
144 r->spd = buffer[3];
145 r->command = buffer[4];
146
147 return 5;
148}
149
150static long File_readInstrumentEffect(InstrumentEffect *effect, const uint8_t *buffer, size_t size)
151{
152 if (size < 40) return -1;
153
154 effect->destWave = get_le32(buffer);
155 effect->srcWave1 = get_le32(buffer + 4);
156 effect->srcWave2 = get_le32(buffer + 8);
157 effect->oscWave = get_le32(buffer + 12);
158 effect->variable1 = get_le32(buffer + 16);
159 effect->variable2 = get_le32(buffer + 20);
160 effect->fxSpeed = get_le32(buffer + 24);
161 effect->oscSpeed = get_le32(buffer + 28);
162 effect->effectType = get_le32(buffer + 32);
163 effect->oscSelect = buffer[36];
164 effect->resetEffect = buffer[37];
165 effect->UNK00 = get_le16(buffer + 38);
166
167 return 40;
168}
169
170static long File_readInstrument(Instrument *instr, const uint8_t *buffer, size_t size)
171{
172 int i, j;
173 long sizeRead;
174
175 if (size < 8712) return -1;
176
177 instr->version = get_le16(buffer);
178
179 memcpy(instr->name, buffer + 2, 32);
180 instr->name[32] = '\0';
181
182 instr->waveform = get_le16(buffer + 34);
183 instr->wavelength = get_le16(buffer + 36);
184 instr->masterVolume = get_le16(buffer + 38);
185 instr->amWave = get_le16(buffer + 40);
186 instr->amSpeed = get_le16(buffer + 42);
187 instr->amLoopPoint = get_le16(buffer + 44);
188 instr->finetune = get_le16(buffer + 46);
189 instr->fmWave = get_le16(buffer + 48);
190 instr->fmSpeed = get_le16(buffer + 50);
191 instr->fmLoopPoint = get_le16(buffer + 52);
192 instr->fmDelay = get_le16(buffer + 54);
193 instr->arpIndex = get_le16(buffer + 56);
194
195 for (i = 0; i < SE_MAXCHANS; i++)
196 instr->m_ResetWave[i] = buffer[58 + i];
197
198 instr->panWave = get_le16(buffer + 74);
199 instr->panSpeed = get_le16(buffer + 76);
200 instr->panLoopPoint = get_le16(buffer + 78);
201 instr->UNK00 = get_le16(buffer + 80);
202 instr->UNK01 = get_le16(buffer + 82);
203 instr->UNK02 = get_le16(buffer + 84);
204 instr->UNK03 = get_le16(buffer + 86);
205 instr->UNK04 = get_le16(buffer + 88);
206 instr->UNK05 = get_le16(buffer + 90);
207
208 buffer += 92; size -= 92;
209
210 for (i = 0; i < 4; i++) {
211 sizeRead = File_readInstrumentEffect(&instr->effects[i], buffer, size);
212 if (sizeRead < 0) return -1;
213 buffer += sizeRead; size -= sizeRead;
214 }
215
216 memcpy(instr->smpFullImportPath, buffer, 192);
217 instr->smpFullImportPath[192] = '\0';
218
219 buffer += 192; size -= 192;
220
221 instr->UNK06 = get_le32(buffer);
222 instr->UNK07 = get_le32(buffer + 4);
223 instr->UNK08 = get_le32(buffer + 8);
224 instr->UNK09 = get_le32(buffer + 12);
225 instr->UNK0A = get_le32(buffer + 16);
226 instr->UNK0B = get_le32(buffer + 20);
227 instr->UNK0C = get_le32(buffer + 24);
228 instr->UNK0D = get_le32(buffer + 28);
229 instr->UNK0E = get_le32(buffer + 32);
230 instr->UNK0F = get_le32(buffer + 36);
231 instr->UNK10 = get_le32(buffer + 40);
232 instr->UNK11 = get_le32(buffer + 44);
233 instr->UNK12 = get_le16(buffer + 48);
234
235 buffer += 50; size -= 50;
236
237 instr->shareSmpDataFromInstr = get_le16(buffer);
238 instr->hasLoop = get_le16(buffer + 2);
239 instr->hasBidiLoop = get_le16(buffer + 4);
240
241 buffer += 6; size -= 6;
242
243 instr->smpStartPoint = get_le32(buffer);
244 instr->smpLoopPoint = get_le32(buffer + 4);
245 instr->smpEndPoint = get_le32(buffer + 8);
246 instr->hasSample = get_le32(buffer + 12);
247 instr->smpLength = get_le32(buffer + 16);
248
249 buffer += 20; size -= 20;
250
251 for (i = 0; i < SE_MAXCHANS; i++) {
252 for (j = 0; j < 0x100; j++) {
253 instr->synthBuffers[i][j] = get_le16(buffer + i * 512 + j * 2);
254 }
255 }
256
257 return 8712;
258}
259
260Song* File_loadSongMem(const uint8_t *buffer, size_t size)
261{
262 int i, j, k;
263 int songVer;
264 Subsong *subs;
265 Order *orderCol;
266 Order *order;
267 Row *row;
268 Instrument *instr;
269 Song *synSong;
270 long sizeRead;
271
272 synSong = (Song *) calloc(1, sizeof(Song));
273 if (!synSong) return NULL;
274
275 /*
276 //unused vars
277 int8_t _local5[] = [0, 0, 0, 0, 0, 0];
278 bool _local2 = false;
279 int _local7 = 0;
280 bool _local8 = true;
281 */
282
283 sizeRead = File_readHeader(&synSong->h, buffer, size);
284 if (sizeRead < 0) goto FAIL;
285 buffer += sizeRead; size -= sizeRead;
286
287 songVer = synSong->h.version;
288 if ((songVer >= 3456) && (songVer <= 3457)){
289 if (synSong->h.subsongNum > 0){
290 synSong->subsongs = (Subsong *) malloc(synSong->h.subsongNum *sizeof(Subsong));
291 if (!synSong->subsongs) goto FAIL;
292
293 for (i = 0; i < synSong->h.subsongNum; i++) {
294 sizeRead = File_readSubSong(synSong->subsongs + i, buffer, size);
295 if (sizeRead < 0) goto FAIL;
296 buffer += sizeRead; size -= sizeRead;
297 }
298
299 synSong->rows = (Row *) malloc(synSong->h.patNum * 64 *sizeof(Row));
300 if (!synSong->rows) goto FAIL;
301
302 for (i = 0, j = synSong->h.patNum * 64; i < j; i++) {
303 sizeRead = File_readRow(synSong->rows + i, buffer, size);
304 if (sizeRead < 0) goto FAIL;
305 buffer += sizeRead; size -= sizeRead;
306 }
307
308 synSong->patNameSizes = (uint32_t *) malloc(synSong->h.patNum * sizeof(uint32_t));
309 if (!synSong->patNameSizes) goto FAIL;
310 synSong->patternNames = calloc(sizeof(char *), synSong->h.patNum);
311 if (!synSong->patternNames) goto FAIL;
312
313 for (i = 0; i < synSong->h.patNum; i++) {
314 if (size < 4) goto FAIL;
315 j = synSong->patNameSizes[i] = get_le32(buffer);
316 buffer += 4; size -= 4;
317
318 if (size < j) goto FAIL;
319
320 synSong->patternNames[i] = malloc(j + sizeof(char));
321 if (!synSong->patternNames[i]) goto FAIL;
322
323 memcpy(synSong->patternNames[i], buffer, j);
324 synSong->patternNames[i][j] = '\0';
325
326 buffer += j; size -= j;
327 }
328
329 synSong->instruments = malloc(synSong->h.instrNum * sizeof(Instrument));
330 if (!synSong->instruments) goto FAIL;
331 synSong->samples = calloc(sizeof(int16_t *), synSong->h.instrNum);
332 if (!synSong->samples) goto FAIL;
333
334 for (i = 0; i < synSong->h.instrNum; i++) {
335 instr = &synSong->instruments[i];
336 sizeRead = File_readInstrument(instr, buffer, size);
337 if (sizeRead < 0) goto FAIL;
338 buffer += sizeRead; size -= sizeRead;
339
340 if (songVer == 3456){
341 instr->shareSmpDataFromInstr = 0;
342 instr->hasLoop = 0;
343 instr->hasBidiLoop = 0;
344 instr->smpStartPoint = 0;
345 instr->smpLoopPoint = 0;
346 instr->smpEndPoint = 0;
347 if (instr->hasSample){
348 instr->smpStartPoint = 0;
349 instr->smpEndPoint = (instr->smpLength / 2);
350 instr->smpLoopPoint = 0;
351 }
352 }
353 if (instr->hasSample){
354 //instr->smpLength is in bytes, I think
355 if (size < instr->smpLength) goto FAIL;
356 synSong->samples[i] = malloc(instr->smpLength);
357 if (!synSong->samples[i]) goto FAIL;
358 memcpy(synSong->samples[i], buffer, instr->smpLength);
359 buffer += instr->smpLength; size -= instr->smpLength;
360 } else {
361 synSong->samples[i] = NULL;
362 }
363
364 }
365 memcpy(synSong->arpTable, buffer, 0x100);
366 buffer += 0x100; size -= 0x100;
367 } else goto FAIL;
368 } else goto FAIL;
369
370 return synSong;
371
372FAIL:
373 File_freeSong(synSong);
374 return NULL;
375}
376
377void File_freeSong(Song *synSong)
378{
379 int i;
380
381 if (synSong) {
382 if (synSong->subsongs) free(synSong->subsongs);
383 if (synSong->rows) free(synSong->rows);
384 if (synSong->patNameSizes) free(synSong->patNameSizes);
385 if (synSong->patternNames) {
386 for (i = 0; i < synSong->h.patNum; i++) {
387 if (synSong->patternNames[i]) free(synSong->patternNames[i]);
388 }
389 free(synSong->patternNames);
390 }
391 if (synSong->instruments) free(synSong->instruments);
392 if (synSong->samples) {
393 for (i = 0; i < synSong->h.instrNum; i++) {
394 if (synSong->samples[i]) free(synSong->samples[i]);
395 }
396 free(synSong->samples);
397 }
398 free(synSong);
399 }
400}
401

Built with git-ssb-web