Mercurial > hg > dmlib
comparison tools/xm2jss.c @ 1246:7bd50496c9ec
Work on improved module conversion.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sat, 07 Mar 2015 18:19:43 +0200 |
parents | 2a0488078b78 |
children | c44fcdc1c2e7 |
comparison
equal
deleted
inserted
replaced
1245:2a0488078b78 | 1246:7bd50496c9ec |
---|---|
421 | 421 |
422 #undef JSFOREACHNOTE1 | 422 #undef JSFOREACHNOTE1 |
423 #undef JSFOREACHNOTE2 | 423 #undef JSFOREACHNOTE2 |
424 | 424 |
425 | 425 |
426 static void jssCopyEnvelope(JSSMODEnvelope *je, JSSEnvelope *e) | 426 static BOOL jssMODWriteEnvelope(FILE *outFile, JSSEnvelope *env, const char *name, const int ninst) |
427 { | 427 { |
428 int i; | 428 int i; |
429 | 429 BOOL ok = |
430 je->flags = e->flags; | 430 dm_fwrite_byte(outFile, env->flags) && |
431 je->npoints = e->npoints; | 431 dm_fwrite_byte(outFile, env->npoints) && |
432 je->sustain = e->sustain; | 432 dm_fwrite_byte(outFile, env->sustain) && |
433 je->loopS = e->loopS; | 433 dm_fwrite_byte(outFile, env->loopS) && |
434 je->loopE = e->loopE; | 434 dm_fwrite_byte(outFile, env->loopE); |
435 | 435 |
436 for (i = 0; i < e->npoints; i++) | 436 for (i = 0; ok && i < env->npoints; i++) |
437 { | 437 { |
438 je->points[i].frame = e->points[i].frame; | 438 ok = |
439 je->points[i].value = e->points[i].value; | 439 dm_fwrite_le16(outFile, env->points[i].frame) && |
440 } | 440 dm_fwrite_le16(outFile, env->points[i].value); |
441 } | |
442 | |
443 if (!ok) | |
444 { | |
445 JSSERROR(DMERR_FWRITE, ok, | |
446 "Failed to write JSSMOD %s-envelope for instrument #%d.\n", | |
447 name, ninst); | |
448 } | |
449 | |
450 return ok; | |
441 } | 451 } |
442 | 452 |
443 | 453 |
444 /* Save a JSSMOD file | 454 /* Save a JSSMOD file |
445 */ | 455 */ |
446 int jssSaveJSSMOD(FILE *outFile, JSSModule *module, int patMode, int flags8, int flags16) | 456 int jssSaveJSSMOD(FILE *outFile, JSSModule *module, int patMode, int flags8, int flags16) |
447 { | 457 { |
448 JSSMODHeader jssH; | 458 JSSMODHeader jssH; |
449 int i, pattern, order, instr, totalSize; | |
450 const size_t patBufSize = 256*1024; // 256kB pattern buffer | 459 const size_t patBufSize = 256*1024; // 256kB pattern buffer |
451 Uint8 *patBuf; | 460 Uint8 *patBuf; |
461 size_t totalSize; | |
462 int index; | |
452 | 463 |
453 // Check the module | 464 // Check the module |
454 if (module == NULL) | 465 if (module == NULL) |
455 JSSERROR(DMERR_NULLPTR, DMERR_NULLPTR, | 466 JSSERROR(DMERR_NULLPTR, DMERR_NULLPTR, |
456 "Module pointer was NULL\n"); | 467 "Module pointer was NULL\n"); |
501 | 512 |
502 totalSize = sizeof(jssH); | 513 totalSize = sizeof(jssH); |
503 dmMsg(1," * JSSMOD-header 0x%04x, %d bytes.\n", JSSMOD_VERSION, totalSize); | 514 dmMsg(1," * JSSMOD-header 0x%04x, %d bytes.\n", JSSMOD_VERSION, totalSize); |
504 | 515 |
505 // Write orders list | 516 // Write orders list |
506 for (totalSize = order = 0; order < module->norders; order++) | 517 for (totalSize = index = 0; index < module->norders; index++) |
507 { | 518 { |
508 int tmp = module->orderList[order]; | 519 int tmp = module->orderList[index]; |
509 if (tmp != jsetNotSet && tmp > module->npatterns) | 520 if (tmp != jsetNotSet && tmp > module->npatterns) |
510 JSSERROR(DMERR_INVALID_DATA, DMERR_INVALID_DATA, | 521 JSSERROR(DMERR_INVALID_DATA, DMERR_INVALID_DATA, |
511 "Orderlist entry #%d has invalid value %d.\n", | 522 "Orderlist entry #%d has invalid value %d.\n", |
512 order, tmp); | 523 index, tmp); |
513 | 524 |
514 if (tmp == jsetNotSet) | 525 if (tmp == jsetNotSet) |
515 tmp = 0xffff; | 526 tmp = 0xffff; |
516 | 527 |
517 if (!dm_fwrite_le16(outFile, tmp)) | 528 if (!dm_fwrite_le16(outFile, tmp)) |
518 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, | 529 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, |
519 "Could not write JSSMOD orders list entry #%d (%d).\n", | 530 "Could not write JSSMOD orders list entry #%d (%d).\n", |
520 order, tmp); | 531 index, tmp); |
521 | 532 |
522 totalSize += sizeof(Uint16); | 533 totalSize += sizeof(Uint16); |
523 } | 534 } |
524 | 535 |
525 dmMsg(1," * %d item orders list, %d bytes.\n", | 536 dmMsg(1," * %d item orders list, %d bytes.\n", |
529 if ((patBuf = dmMalloc(patBufSize)) == NULL) | 540 if ((patBuf = dmMalloc(patBufSize)) == NULL) |
530 JSSERROR(DMERR_MALLOC, DMERR_MALLOC, | 541 JSSERROR(DMERR_MALLOC, DMERR_MALLOC, |
531 "Error allocating memory for pattern compression buffer.\n"); | 542 "Error allocating memory for pattern compression buffer.\n"); |
532 | 543 |
533 // Convert and write patterns | 544 // Convert and write patterns |
534 for (totalSize = pattern = 0; pattern < module->npatterns; pattern++) | 545 for (totalSize = index = 0; index < module->npatterns; index++) |
535 if (module->patterns[pattern] != NULL) | 546 if (module->patterns[index] != NULL) |
536 { | 547 { |
537 JSSPattern *pat = module->patterns[pattern]; | 548 JSSPattern *pattern = module->patterns[index]; |
538 JSSMODPattern patHead; | 549 size_t dataSize = 0; |
539 size_t finalSize = 0; | 550 int ret; |
540 | 551 |
541 if (pat->nrows > jsetMaxRows) | 552 if (pattern->nrows > jsetMaxRows) |
542 JSSERROR(DMERR_INVALID_DATA, DMERR_INVALID_DATA, | 553 JSSERROR(DMERR_INVALID_DATA, DMERR_INVALID_DATA, |
543 "Pattern #%d has %d rows > %d max.\n", | 554 "Pattern #%d has %d rows > %d max.\n", |
544 pattern, pat->nrows, jsetMaxRows); | 555 index, pattern->nrows, jsetMaxRows); |
545 | 556 |
546 switch (patMode) | 557 switch (patMode) |
547 { | 558 { |
548 case PATMODE_RAW_HORIZ: | 559 case PATMODE_RAW_HORIZ: |
549 i = jssConvertPatternRawHoriz(patBuf, patBufSize, &finalSize, pat); | 560 ret = jssConvertPatternRawHoriz(patBuf, patBufSize, &dataSize, pattern); |
550 break; | 561 break; |
551 case PATMODE_COMP_HORIZ: | 562 case PATMODE_COMP_HORIZ: |
552 i = jssConvertPatternCompHoriz(patBuf, patBufSize, &finalSize, pat); | 563 ret = jssConvertPatternCompHoriz(patBuf, patBufSize, &dataSize, pattern); |
553 break; | 564 break; |
554 case PATMODE_RAW_VERT: | 565 case PATMODE_RAW_VERT: |
555 i = jssConvertPatternRawVert(patBuf, patBufSize, &finalSize, pat); | 566 ret = jssConvertPatternRawVert(patBuf, patBufSize, &dataSize, pattern); |
556 break; | 567 break; |
557 case PATMODE_COMP_VERT: | 568 case PATMODE_COMP_VERT: |
558 i = jssConvertPatternCompVert(patBuf, patBufSize, &finalSize, pat); | 569 ret = jssConvertPatternCompVert(patBuf, patBufSize, &dataSize, pattern); |
559 break; | 570 break; |
560 case PATMODE_RAW_ELEM: | 571 case PATMODE_RAW_ELEM: |
561 i = jssConvertPatternRawElem(patBuf, patBufSize, &finalSize, pat); | 572 ret = jssConvertPatternRawElem(patBuf, patBufSize, &dataSize, pattern); |
562 break; | 573 break; |
563 default: | 574 default: |
564 dmFree(patBuf); | |
565 JSSERROR(DMERR_INVALID_DATA, DMERR_INVALID_DATA, | 575 JSSERROR(DMERR_INVALID_DATA, DMERR_INVALID_DATA, |
566 "Unsupported pattern conversion mode %d for pattern #%d.\n", | 576 "Unsupported pattern conversion mode %d for pattern #%d.\n", |
567 patMode, pattern); | 577 patMode, index); |
568 } | 578 } |
569 | 579 |
570 if (i != DMERR_OK) | 580 if (ret != DMERR_OK) |
571 { | 581 JSSERROR(ret, ret, "Error converting pattern data #%d.\n", |
572 dmFree(patBuf); | 582 pattern); |
573 JSSERROR(i, i, "Error converting pattern data #%d\n", pattern); | 583 |
574 } | 584 dmMsg(3, " - Pattern %d size %d bytes\n", index, dataSize); |
575 | 585 totalSize += dataSize + sizeof(JSSMODPattern); |
576 dmMsg(3, " - Pattern %d size %d bytes\n", pattern, finalSize); | 586 |
577 patHead.nrows = pat->nrows; | 587 if (!dm_fwrite_le32(outFile, dataSize) || |
578 patHead.size = finalSize; | 588 !dm_fwrite_le16(outFile, pattern->nrows) || |
579 totalSize += finalSize + sizeof(patHead); | 589 !dm_fwrite_str(outFile, patBuf, dataSize)) |
580 | |
581 if (fwrite(&patHead, sizeof(patHead), 1, outFile) != 1) | |
582 { | |
583 dmFree(patBuf); | |
584 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, | 590 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, |
585 "Error writing pattern #%d header\n", pattern); | 591 "Error writing JSSMOD pattern #%d.\n", |
586 } | 592 index); |
587 | 593 } |
588 if (fwrite(patBuf, sizeof(Uint8), finalSize, outFile) != finalSize) | 594 else |
589 { | 595 JSSERROR(DMERR_NULLPTR, DMERR_NULLPTR, |
590 dmFree(patBuf); | 596 "Pattern #%d was NULL.\n", index); |
597 | |
598 dmFree(patBuf); | |
599 dmMsg(1," * %d patterns, %d bytes.\n", | |
600 module->npatterns, totalSize); | |
601 | |
602 // Write extended instruments | |
603 for (totalSize = index = 0; index < module->nextInstruments; index++) | |
604 if (module->extInstruments[index] != NULL) | |
605 { | |
606 JSSExtInstrument *einst = module->extInstruments[index]; | |
607 int i; | |
608 | |
609 BOOL ok = | |
610 dm_fwrite_byte(outFile, einst->nsamples) && | |
611 dm_fwrite_byte(outFile, einst->vibratoType) && | |
612 dm_fwrite_le16(outFile, einst->vibratoSweep) && | |
613 dm_fwrite_le16(outFile, einst->vibratoDepth) && | |
614 dm_fwrite_le16(outFile, einst->vibratoRate) && | |
615 dm_fwrite_le16(outFile, einst->fadeOut); | |
616 | |
617 for (i = 0; ok && i < jsetNNotes; i++) | |
618 { | |
619 int snum = einst->sNumForNotes[i]; | |
620 Uint32 tmp = (snum != jsetNotSet) ? snum + 1 : 0; | |
621 ok = dm_fwrite_le32(outFile, tmp); | |
622 } | |
623 | |
624 if (!ok || | |
625 !jssMODWriteEnvelope(outFile, &einst->volumeEnv, "volume", index) || | |
626 !jssMODWriteEnvelope(outFile, &einst->panningEnv, "panning", index)) | |
591 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, | 627 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, |
592 "Error writing pattern #%d data\n", pattern); | 628 "Error writing JSSMOD extended instrument #%d.\n", |
593 } | 629 index); |
594 } | 630 |
595 else | 631 totalSize += sizeof(JSSMODExtInstrument); |
596 JSSERROR(DMERR_NULLPTR, DMERR_NULLPTR, | 632 } |
597 "Pattern #%d was NULL.\n", pattern); | 633 else |
598 | 634 JSSWARNING(DMERR_NULLPTR, DMERR_NULLPTR, |
599 dmFree(patBuf); | 635 "Extended instrument #%d NULL!\n", |
600 dmMsg(1," * %d patterns, %d bytes.\n", module->npatterns, totalSize); | 636 index); |
601 | 637 |
602 // Write extended instruments | 638 dmMsg(1," * %d Extended Instruments, %d bytes.\n", |
603 for (totalSize = instr = 0; instr < module->nextInstruments; instr++) | 639 module->nextInstruments, totalSize); |
604 if (module->extInstruments[instr] != NULL) | 640 |
605 { | 641 // Write sample instrument headers |
606 JSSExtInstrument *einst = module->extInstruments[instr]; | 642 for (totalSize = index = 0; index < module->ninstruments; index++) |
607 JSSMODExtInstrument jssE; | 643 if (module->instruments[index] != NULL) |
608 | 644 { |
609 dmMemset(&jssE, 0, sizeof(jssE)); | 645 JSSInstrument *inst = module->instruments[index]; |
610 | 646 Uint8 convFlags = (inst->flags & jsf16bit) ? flags16 : flags8; |
611 // Create header | 647 if (inst->data != NULL) |
612 jssE.nsamples = einst->nsamples; | 648 convFlags |= jsampHasData; |
613 for (i = 0; i < jsetNNotes; i++) | 649 |
614 { | 650 // Write instrument header to file |
615 int snum = einst->sNumForNotes[i]; | 651 if (!dm_fwrite_le32(outFile, inst->size) || |
616 jssE.sNumForNotes[i] = (snum != jsetNotSet) ? snum + 1: 0; | 652 !dm_fwrite_le32(outFile, inst->loopS) || |
617 } | 653 !dm_fwrite_le32(outFile, inst->loopE) || |
618 | 654 !dm_fwrite_le16(outFile, inst->flags) || |
619 jssCopyEnvelope(&jssE.volumeEnv, &(einst->volumeEnv)); | 655 !dm_fwrite_le16(outFile, inst->C4BaseSpeed) || |
620 jssCopyEnvelope(&jssE.panningEnv, &(einst->panningEnv)); | 656 !dm_fwrite_le16(outFile, inst->ERelNote) || |
621 jssE.vibratoType = einst->vibratoType; | 657 !dm_fwrite_le16(outFile, inst->EFineTune) || |
622 jssE.vibratoSweep = einst->vibratoSweep; | 658 !dm_fwrite_le16(outFile, inst->EPanning) || |
623 jssE.vibratoDepth = einst->vibratoDepth; | 659 !dm_fwrite_byte(outFile, inst->volume) || |
624 jssE.fadeOut = einst->fadeOut; | 660 !dm_fwrite_byte(outFile, inst->convFlags)) |
625 | |
626 // Write to file | |
627 totalSize += sizeof(jssE); | |
628 if (fwrite(&jssE, sizeof(jssE), 1, outFile) != 1) | |
629 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, | 661 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, |
630 "Could not write JSSMOD extended instrument #%d to file!\n", instr); | 662 "Error writing JSSMOD instrument #%d.\n", |
631 } else | 663 index); |
632 JSSWARNING(DMERR_NULLPTR, DMERR_NULLPTR, "Extended instrument #%d NULL!\n", instr); | 664 |
633 | 665 totalSize += sizeof(JSSMODInstrument); |
634 dmMsg(1," * %d Extended Instruments, %d bytes.\n", module->nextInstruments, totalSize); | |
635 | |
636 // Write sample instrument headers | |
637 for (totalSize = instr = 0; instr < module->ninstruments; instr++) | |
638 if (module->instruments[instr] != NULL) | |
639 { | |
640 JSSInstrument *inst = module->instruments[instr]; | |
641 JSSMODInstrument jssI; | |
642 | |
643 dmMemset(&jssI, 0, sizeof(jssI)); | |
644 | |
645 // Create header | |
646 jssI.size = inst->size; | |
647 jssI.loopS = inst->loopS; | |
648 jssI.loopE = inst->loopE; | |
649 jssI.volume = inst->volume; | |
650 jssI.flags = inst->flags; | |
651 jssI.C4BaseSpeed = inst->C4BaseSpeed; | |
652 jssI.ERelNote = inst->ERelNote; | |
653 jssI.EFineTune = inst->EFineTune; | |
654 jssI.EPanning = inst->EPanning; | |
655 jssI.convFlags = (inst->flags & jsf16bit) ? flags16 : flags8; | |
656 if (inst->data != NULL) | |
657 jssI.convFlags |= jsampHasData; | |
658 | |
659 // Write to file | |
660 totalSize += sizeof(jssI); | |
661 if (fwrite(&jssI, sizeof(jssI), 1, outFile) != 1) | |
662 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, | |
663 "Could not write JSSMOD instrument #%d to file!\n", instr); | |
664 } | 666 } |
665 else | 667 else |
666 JSSWARNING(DMERR_NULLPTR, DMERR_NULLPTR, | 668 JSSWARNING(DMERR_NULLPTR, DMERR_NULLPTR, |
667 "Instrument #%d NULL!\n", instr); | 669 "Instrument #%d NULL!\n", index); |
668 | 670 |
669 dmMsg(1," * %d Instrument headers, %d bytes.\n", | 671 dmMsg(1," * %d Instrument headers, %d bytes.\n", |
670 module->ninstruments, totalSize); | 672 module->ninstruments, totalSize); |
671 | 673 |
672 // Write sample data | 674 // Write sample data |
673 for (totalSize = instr = 0; instr < module->ninstruments; instr++) | 675 for (totalSize = index = 0; index < module->ninstruments; index++) |
674 { | 676 { |
675 JSSInstrument *inst = module->instruments[instr]; | 677 JSSInstrument *inst = module->instruments[index]; |
676 if (inst != NULL && inst->data != NULL) | 678 if (inst != NULL && inst->data != NULL) |
677 { | 679 { |
678 size_t bsize = inst->size; | 680 size_t bsize = inst->size; |
679 if (inst->flags & jsf16bit) | 681 if (inst->flags & jsf16bit) |
680 { | 682 { |
685 { | 687 { |
686 bsize *= sizeof(Uint8); | 688 bsize *= sizeof(Uint8); |
687 jssEncodeSample8(inst->data, inst->size, flags8); | 689 jssEncodeSample8(inst->data, inst->size, flags8); |
688 } | 690 } |
689 | 691 |
690 if (fwrite(inst->data, sizeof(Uint16), bsize, outFile) != bsize) | 692 if (!dm_fwrite_str(outFile, inst->data, bsize)) |
691 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, | 693 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, |
692 "Error writing JSSMOD sample #%d.\n", instr); | 694 "Error writing JSSMOD sample data for instrument #%d.\n", |
695 index); | |
693 | 696 |
694 totalSize += bsize; | 697 totalSize += bsize; |
695 } | 698 } |
696 } | 699 } |
697 dmMsg(1," * %d samples, %d bytes.\n", module->ninstruments, totalSize); | 700 |
701 dmMsg(1," * %d samples, %d bytes.\n", | |
702 module->ninstruments, totalSize); | |
698 | 703 |
699 return DMERR_OK; | 704 return DMERR_OK; |
700 } | 705 } |
701 | 706 |
702 | 707 |