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