Mercurial > hg > dmlib
comparison minijss/jloadjss.c @ 777:ed60a7ee3ebb
Change JSSMOD loader to use DMResources.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 24 May 2013 01:19:11 +0300 |
parents | c430112449a7 |
children | 97ecc0a9c21f |
comparison
equal
deleted
inserted
replaced
776:9acebca96dcc | 777:ed60a7ee3ebb |
---|---|
14 # define JM_SUP_PATMODE_4 1 | 14 # define JM_SUP_PATMODE_4 1 |
15 # define JM_SUP_PATMODE_5 1 | 15 # define JM_SUP_PATMODE_5 1 |
16 #endif | 16 #endif |
17 | 17 |
18 | 18 |
19 static BOOL jsGetBufData(Uint8 **buf, size_t *bufLeft, void *data, const size_t dataSize) | 19 #define JSGETBUF(XV, XT) if (!dmf_read_str(inFile, XV, sizeof(XT))) return DMERR_OUT_OF_DATA |
20 { | 20 #define JSGETBYTE(XV) if (!dmf_read_byte(inFile, XV)) return DMERR_OUT_OF_DATA |
21 if (*bufLeft >= dataSize) | |
22 { | |
23 memcpy(data, *buf, dataSize); | |
24 *buf += dataSize; | |
25 *bufLeft -= dataSize; | |
26 return TRUE; | |
27 } | |
28 else | |
29 return FALSE; | |
30 } | |
31 | |
32 | |
33 static BOOL jsGetBufByte(Uint8 **buf, size_t *bufLeft, Uint8 *data) | |
34 { | |
35 if (*bufLeft > 0) | |
36 { | |
37 *data = **buf; | |
38 (*buf)++; | |
39 (*bufLeft)--; | |
40 return TRUE; | |
41 } | |
42 else | |
43 return FALSE; | |
44 } | |
45 | |
46 | |
47 #define JSGETBUF(XV, XT) if (!jsGetBufData(buf, bufLeft, XV, sizeof(XT))) return DMERR_OUT_OF_DATA | |
48 #define JSGETBYTE(XV) if (!jsGetBufByte(buf, bufLeft, XV)) return DMERR_OUT_OF_DATA | |
49 | 21 |
50 | 22 |
51 #if defined(JM_SUP_PATMODE_1) || defined(JM_SUP_PATMODE_3) | 23 #if defined(JM_SUP_PATMODE_1) || defined(JM_SUP_PATMODE_3) |
52 static int jssGetConvertedNote(Uint8 **buf, size_t *bufLeft, JSSNote *note) | 24 static int jssGetConvertedNote(DMResource *inFile, JSSNote *note) |
53 { | 25 { |
54 Uint8 tmp; | 26 Uint8 tmp; |
55 | 27 |
56 JSGETBYTE(&tmp); | 28 JSGETBYTE(&tmp); |
57 | 29 |
78 } | 50 } |
79 #endif | 51 #endif |
80 | 52 |
81 | 53 |
82 #if defined(JM_SUP_PATMODE_2) || defined(JM_SUP_PATMODE_4) | 54 #if defined(JM_SUP_PATMODE_2) || defined(JM_SUP_PATMODE_4) |
83 static int jssGetCompressedNote(Uint8 **buf, size_t *bufLeft, JSSNote *note) | 55 static int jssGetCompressedNote(DMResource *inFile, JSSNote *note) |
84 { | 56 { |
85 Uint8 packb, tmp; | 57 Uint8 packb, tmp; |
86 | 58 |
87 JSGETBYTE(&packb); | 59 JSGETBYTE(&packb); |
88 if (packb & 0x80) | 60 if (packb & 0x80) |
149 } | 121 } |
150 #endif | 122 #endif |
151 | 123 |
152 | 124 |
153 #ifdef JM_SUP_PATMODE_2 | 125 #ifdef JM_SUP_PATMODE_2 |
154 static int jssGetPatternCompHoriz(Uint8 *buf, size_t *bufLeft, JSSPattern *pattern) | 126 static int jssGetPatternCompHoriz(DMResource *inFile, JSSPattern *pattern) |
155 { | 127 { |
156 int row, channel; | 128 int row, channel; |
157 | 129 |
158 assert(buf != NULL); | 130 assert(buf != NULL); |
159 assert(pattern != NULL); | 131 assert(pattern != NULL); |
160 | 132 |
161 for (row = 0; row < pattern->nrows; row++) | 133 for (row = 0; row < pattern->nrows; row++) |
162 for (channel = 0; channel < pattern->nchannels; channel++) | 134 for (channel = 0; channel < pattern->nchannels; channel++) |
163 { | 135 { |
164 JSSNote *note = &pattern->data[(pattern->nchannels * row) + channel]; | 136 JSSNote *note = &pattern->data[(pattern->nchannels * row) + channel]; |
165 int res = jssGetCompressedNote(&buf, bufLeft, note); | 137 int res = jssGetCompressedNote(inFile, note); |
166 if (res != DMERR_OK) | 138 if (res != DMERR_OK) |
167 JSSERROR(res, res, "Error uncompressing note on row=%d, chn=%d\n", row, channel); | 139 JSSERROR(res, res, "Error uncompressing note on row=%d, chn=%d\n", row, channel); |
168 } | 140 } |
169 | 141 |
170 return DMERR_OK; | 142 return DMERR_OK; |
171 } | 143 } |
172 #endif | 144 #endif |
173 | 145 |
174 | 146 |
175 #ifdef JM_SUP_PATMODE_4 | 147 #ifdef JM_SUP_PATMODE_4 |
176 static int jssGetPatternCompVert(Uint8 *buf, size_t *bufLeft, JSSPattern *pattern) | 148 static int jssGetPatternCompVert(DMResource *inFile, JSSPattern *pattern) |
177 { | 149 { |
178 int row, channel; | 150 int row, channel; |
179 | 151 |
180 assert(buf != NULL); | 152 assert(buf != NULL); |
181 assert(pattern != NULL); | 153 assert(pattern != NULL); |
182 | 154 |
183 for (channel = 0; channel < pattern->nchannels; channel++) | 155 for (channel = 0; channel < pattern->nchannels; channel++) |
184 for (row = 0; row < pattern->nrows; row++) | 156 for (row = 0; row < pattern->nrows; row++) |
185 { | 157 { |
186 JSSNote *note = &pattern->data[(pattern->nchannels * row) + channel]; | 158 JSSNote *note = &pattern->data[(pattern->nchannels * row) + channel]; |
187 int res = jssGetCompressedNote(&buf, bufLeft, note); | 159 int res = jssGetCompressedNote(inFile, note); |
188 if (res != DMERR_OK) | 160 if (res != DMERR_OK) |
189 JSSERROR(res, res, "Error uncompressing note on row=%d, chn=%d\n", row, channel); | 161 JSSERROR(res, res, "Error uncompressing note on row=%d, chn=%d\n", row, channel); |
190 } | 162 } |
191 | 163 |
192 return DMERR_OK; | 164 return DMERR_OK; |
193 } | 165 } |
194 #endif | 166 #endif |
195 | 167 |
196 | 168 |
197 #ifdef JM_SUP_PATMODE_1 | 169 #ifdef JM_SUP_PATMODE_1 |
198 static int jssGetPatternRawHoriz(Uint8 *buf, size_t *bufLeft, JSSPattern *pattern) | 170 static int jssGetPatternRawHoriz(DMResource *inFile, JSSPattern *pattern) |
199 { | 171 { |
200 int row, channel; | 172 int row, channel; |
201 | 173 |
202 assert(buf != NULL); | 174 assert(buf != NULL); |
203 assert(pattern != NULL); | 175 assert(pattern != NULL); |
204 | 176 |
205 for (row = 0; row < pattern->nrows; row++) | 177 for (row = 0; row < pattern->nrows; row++) |
206 for (channel = 0; channel < pattern->nchannels; channel++) | 178 for (channel = 0; channel < pattern->nchannels; channel++) |
207 { | 179 { |
208 JSSNote *note = &pattern->data[(pattern->nchannels * row) + channel]; | 180 JSSNote *note = &pattern->data[(pattern->nchannels * row) + channel]; |
209 int res = jssGetConvertedNote(&buf, bufLeft, note); | 181 int res = jssGetConvertedNote(inFile, note); |
210 if (res != DMERR_OK) | 182 if (res != DMERR_OK) |
211 JSSERROR(res, res, "Error converting note on row=%d, chn=%d\n", row, channel); | 183 JSSERROR(res, res, "Error converting note on row=%d, chn=%d\n", row, channel); |
212 } | 184 } |
213 | 185 |
214 return DMERR_OK; | 186 return DMERR_OK; |
215 } | 187 } |
216 #endif | 188 #endif |
217 | 189 |
218 | 190 |
219 #ifdef JM_SUP_PATMODE_3 | 191 #ifdef JM_SUP_PATMODE_3 |
220 static int jssGetPatternRawVert(Uint8 *buf, size_t *bufLeft, JSSPattern *pattern) | 192 static int jssGetPatternRawVert(DMResource *inFile, JSSPattern *pattern) |
221 { | 193 { |
222 int row, channel; | 194 int row, channel; |
223 | 195 |
224 assert(buf != NULL); | 196 assert(buf != NULL); |
225 assert(pattern != NULL); | 197 assert(pattern != NULL); |
226 | 198 |
227 for (channel = 0; channel < pattern->nchannels; channel++) | 199 for (channel = 0; channel < pattern->nchannels; channel++) |
228 for (row = 0; row < pattern->nrows; row++) | 200 for (row = 0; row < pattern->nrows; row++) |
229 { | 201 { |
230 JSSNote *note = &pattern->data[(pattern->nchannels * row) + channel]; | 202 JSSNote *note = &pattern->data[(pattern->nchannels * row) + channel]; |
231 int res = jssGetConvertedNote(&buf, bufLeft, note); | 203 int res = jssGetConvertedNote(inFile, note); |
232 if (res != DMERR_OK) | 204 if (res != DMERR_OK) |
233 JSSERROR(res, res, "Error converting note on row=%d, chn=%d\n", row, channel); | 205 JSSERROR(res, res, "Error converting note on row=%d, chn=%d\n", row, channel); |
234 } | 206 } |
235 | 207 |
236 return DMERR_OK; | 208 return DMERR_OK; |
239 | 211 |
240 | 212 |
241 #ifdef JM_SUP_PATMODE_5 | 213 #ifdef JM_SUP_PATMODE_5 |
242 | 214 |
243 #undef JSGETBYTE | 215 #undef JSGETBYTE |
244 #define JSGETBYTE(XV) if (!jsGetBufByte(&buf, bufLeft, XV)) return DMERR_OUT_OF_DATA | 216 #define JSGETBYTE(XV) if (!dmf_read_byte(inFile, XV)) return DMERR_OUT_OF_DATA |
245 | 217 |
246 #define JSFOREACHNOTE1 \ | 218 #define JSFOREACHNOTE1 \ |
247 for (channel = 0; channel < pattern->nchannels; channel++) \ | 219 for (channel = 0; channel < pattern->nchannels; channel++) \ |
248 for (row = 0; row < pattern->nrows; row++) { \ | 220 for (row = 0; row < pattern->nrows; row++) { \ |
249 JSSNote *note = pattern->data + (pattern->nchannels * row) + channel; | 221 JSSNote *note = pattern->data + (pattern->nchannels * row) + channel; |
250 | 222 |
251 #define JSFOREACHNOTE2 } | 223 #define JSFOREACHNOTE2 } |
252 | 224 |
253 static int jssGetPatternRawVertElem(Uint8 *buf, size_t *bufLeft, JSSPattern *pattern) | 225 static int jssGetPatternRawVertElem(DMResource *inFile, JSSPattern *pattern) |
254 { | 226 { |
255 int row, channel; | 227 int row, channel; |
256 Uint8 tmp; | 228 Uint8 tmp; |
257 | 229 |
258 assert(buf != NULL); | 230 assert(buf != NULL); |
294 | 266 |
295 | 267 |
296 #undef JSGETBUF | 268 #undef JSGETBUF |
297 #undef JSGETBYTE | 269 #undef JSGETBYTE |
298 #define JSGETBUF(XV, XT) do { \ | 270 #define JSGETBUF(XV, XT) do { \ |
299 if (!jsGetBufData(&buf, &bufLeft, XV, sizeof(XT))) \ | 271 if (!dmf_read_str(inFile, XV, sizeof(XT))) \ |
300 JSSERROR(DMERR_OUT_OF_DATA, DMERR_OUT_OF_DATA, \ | 272 JSSERROR(DMERR_OUT_OF_DATA, DMERR_OUT_OF_DATA, \ |
301 "Out of data at getting " # XT " (%d bytes)\n", sizeof(XT)); \ | 273 "Out of data at getting " # XT " (%d bytes)\n", sizeof(XT)); \ |
302 } while (0) | 274 } while (0) |
303 #define JSGETBYTE(XV) if (!jsGetBufByte(&buf, &bufLeft, XV)) return DMERR_OUT_OF_DATA | 275 #define JSGETBYTE(XV) if (!dmf_read_byte(inFile, XV)) return DMERR_OUT_OF_DATA |
304 | 276 |
305 | 277 |
306 #ifdef JM_SUP_EXT_INSTR | 278 #ifdef JM_SUP_EXT_INSTR |
307 static void jssCopyEnvelope(JSSEnvelope *e, JSSMODEnvelope *je) | 279 static void jssCopyEnvelope(JSSEnvelope *e, JSSMODEnvelope *je) |
308 { | 280 { |
321 } | 293 } |
322 } | 294 } |
323 #endif | 295 #endif |
324 | 296 |
325 | 297 |
326 int jssLoadJSSMOD(Uint8 *bufStart, const size_t bufSize, JSSModule **ppModule) | 298 int jssLoadJSSMOD(DMResource *inFile, JSSModule **ppModule) |
327 { | 299 { |
328 JSSModule *module; | 300 JSSModule *module; |
329 JSSMODHeader jssH; | 301 JSSMODHeader jssH; |
330 Uint8 *buf = bufStart; | |
331 size_t bufLeft = bufSize; | |
332 int index; | 302 int index; |
333 | 303 |
334 assert(ppModule != NULL); | |
335 assert(bufStart != NULL); | |
336 *ppModule = NULL; | 304 *ppModule = NULL; |
337 | 305 |
338 // Check the JSSMOD header | 306 // Check the JSSMOD header |
339 memset(&jssH, 0, sizeof(jssH)); | 307 memset(&jssH, 0, sizeof(jssH)); |
340 JSGETBUF(&jssH, JSSMODHeader); | 308 JSGETBUF(&jssH, JSSMODHeader); |
384 // Parse the patterns | 352 // Parse the patterns |
385 for (index = 0; index < module->npatterns; index++) | 353 for (index = 0; index < module->npatterns; index++) |
386 { | 354 { |
387 JSSMODPattern jssP; | 355 JSSMODPattern jssP; |
388 int result = DMERR_INVALID_DATA; | 356 int result = DMERR_INVALID_DATA; |
389 size_t bufSize; | |
390 | 357 |
391 // Get header and check size | 358 // Get header and check size |
392 memset(&jssP, 0, sizeof(jssP)); | 359 memset(&jssP, 0, sizeof(jssP)); |
393 JSGETBUF(&jssP, JSSMODPattern); | 360 JSGETBUF(&jssP, JSSMODPattern); |
394 bufSize = jssP.size; | |
395 if (bufLeft < jssP.size) | |
396 { | |
397 JSSERROR(DMERR_OUT_OF_DATA, DMERR_OUT_OF_DATA, | |
398 "Out of data for pattern #%d.\n", index); | |
399 } | |
400 | 361 |
401 // Allocate pattern | 362 // Allocate pattern |
402 module->patterns[index] = jssAllocatePattern(jssP.nrows, module->nchannels); | 363 module->patterns[index] = jssAllocatePattern(jssP.nrows, module->nchannels); |
403 if (module->patterns[index] == NULL) | 364 if (module->patterns[index] == NULL) |
404 { | 365 { |
409 // Get pattern data | 370 // Get pattern data |
410 switch (jssH.patMode) | 371 switch (jssH.patMode) |
411 { | 372 { |
412 #ifdef JM_SUP_PATMODE_1 | 373 #ifdef JM_SUP_PATMODE_1 |
413 case PATMODE_RAW_HORIZ: | 374 case PATMODE_RAW_HORIZ: |
414 result = jssGetPatternRawHoriz(buf, &bufSize, module->patterns[index]); | 375 result = jssGetPatternRawHoriz(inFile, module->patterns[index]); |
415 break; | 376 break; |
416 #endif | 377 #endif |
417 #ifdef JM_SUP_PATMODE_2 | 378 #ifdef JM_SUP_PATMODE_2 |
418 case PATMODE_COMP_HORIZ: | 379 case PATMODE_COMP_HORIZ: |
419 result = jssGetPatternCompHoriz(buf, &bufSize, module->patterns[index]); | 380 result = jssGetPatternCompHoriz(inFile, module->patterns[index]); |
420 break; | 381 break; |
421 #endif | 382 #endif |
422 #ifdef JM_SUP_PATMODE_3 | 383 #ifdef JM_SUP_PATMODE_3 |
423 case PATMODE_RAW_VERT: | 384 case PATMODE_RAW_VERT: |
424 result = jssGetPatternRawVert(buf, &bufSize, module->patterns[index]); | 385 result = jssGetPatternRawVert(inFile, module->patterns[index]); |
425 break; | 386 break; |
426 #endif | 387 #endif |
427 #ifdef JM_SUP_PATMODE_4 | 388 #ifdef JM_SUP_PATMODE_4 |
428 case PATMODE_COMP_VERT: | 389 case PATMODE_COMP_VERT: |
429 result = jssGetPatternCompVert(buf, &bufSize, module->patterns[index]); | 390 result = jssGetPatternCompVert(inFile, module->patterns[index]); |
430 break; | 391 break; |
431 #endif | 392 #endif |
432 #ifdef JM_SUP_PATMODE_5 | 393 #ifdef JM_SUP_PATMODE_5 |
433 case PATMODE_RAW_ELEM: | 394 case PATMODE_RAW_ELEM: |
434 result = jssGetPatternRawVertElem(buf, &bufSize, module->patterns[index]); | 395 result = jssGetPatternRawVertElem(inFile, module->patterns[index]); |
435 break; | 396 break; |
436 #endif | 397 #endif |
437 default: | 398 default: |
438 JSSERROR(DMERR_INVALID_DATA, DMERR_INVALID_DATA, | 399 JSSERROR(DMERR_INVALID_DATA, DMERR_INVALID_DATA, |
439 "Unsupported pattern mode %d. Check compilation options.", jssH.patMode); | 400 "Unsupported pattern mode %d. Check compilation options.", jssH.patMode); |
440 break; | 401 break; |
441 } | 402 } |
442 | 403 |
443 if (bufSize > 0) | |
444 { | |
445 JSSWARNING(DMERR_EXTRA_DATA, DMERR_EXTRA_DATA, | |
446 "Unparsed data after pattern (%d bytes), possibly broken file.\n", bufSize); | |
447 } | |
448 | |
449 if (result != DMERR_OK) | 404 if (result != DMERR_OK) |
450 { | 405 { |
451 JSSERROR(result, result, "Error in unpacking pattern #%i data\n", index); | 406 JSSERROR(result, result, "Error in unpacking pattern #%i data\n", index); |
452 } | 407 } |
453 | |
454 buf += jssP.size; | |
455 bufLeft -= jssP.size; | |
456 } | 408 } |
457 | 409 |
458 #ifdef JM_SUP_EXT_INSTR | 410 #ifdef JM_SUP_EXT_INSTR |
459 // Read extended instruments | 411 // Read extended instruments |
460 for (index = 0; index < module->nextInstruments; index++) | 412 for (index = 0; index < module->nextInstruments; index++) |
536 if (inst->flags & jsf16bit) | 488 if (inst->flags & jsf16bit) |
537 sz = inst->size * sizeof(Uint16); | 489 sz = inst->size * sizeof(Uint16); |
538 else | 490 else |
539 sz = inst->size * sizeof(Uint8); | 491 sz = inst->size * sizeof(Uint8); |
540 | 492 |
541 // Check if we can get as much? | |
542 if (bufLeft < sz) | |
543 { | |
544 JSSERROR(DMERR_OUT_OF_DATA, DMERR_OUT_OF_DATA, | |
545 "Out of data for instrument sample #%d (%d < %d)\n", | |
546 index, bufLeft, sz); | |
547 } | |
548 | |
549 // Allocate | 493 // Allocate |
550 if ((inst->data = dmMalloc(sz)) == NULL) | 494 if ((inst->data = dmMalloc(sz)) == NULL) |
551 { | 495 { |
552 JSSERROR(DMERR_MALLOC, DMERR_MALLOC, | 496 JSSERROR(DMERR_MALLOC, DMERR_MALLOC, |
553 "Could not allocate sample data #%d\n", index); | 497 "Could not allocate sample data #%d\n", index); |
554 } | 498 } |
555 | 499 |
556 // Copy data | 500 // Copy data |
557 memcpy(inst->data, buf, sz); | 501 if (!dmf_read_str(inFile, inst->data, sz)) |
558 buf += sz; | 502 { |
559 bufLeft -= sz; | 503 JSSERROR(DMERR_FREAD, DMERR_FREAD, |
504 "Could not read sample data for #%d\n", index); | |
505 } | |
560 | 506 |
561 // Convert, if needed | 507 // Convert, if needed |
562 if (inst->flags & jsf16bit) | 508 if (inst->flags & jsf16bit) |
563 jssDecodeSample16(inst->data, inst->size, inst->convFlags); | 509 jssDecodeSample16(inst->data, inst->size, inst->convFlags); |
564 else | 510 else |