SHARE
TWEET

Famitone 3.2 Unofficial - Cross Platform

a guest Mar 3rd, 2018 260 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // text2vol.cpp  version 3.2: Defines the entry point for the console application.
  2. // doug fraker 2016-7, adding volume column, with values 70-7f
  3. // and allow all notes, but removing pal support
  4.  
  5. #define _CRT_SECURE_NO_WARNINGS
  6.  
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stdio.h>
  10. #include <memory.h>
  11.  
  12. #define OUT_NESASM 0
  13. #define OUT_CA65 1
  14. #define OUT_ASM6 2
  15.  
  16. char DB[8];
  17. char DW[8];
  18. char LL[8];
  19. char LOW[8];
  20.  
  21. #define MIN_PATTERN_LEN 6
  22. #define MAX_REPEAT_CNT 60
  23.  
  24. #define MAX_SUB_SONGS ((256 - 5) / 14)
  25. #define MAX_ROWS 256
  26. #define MAX_PATTERNS (128 * MAX_SUB_SONGS)
  27. #define MAX_ORDER (128 * MAX_SUB_SONGS)
  28. #define MAX_INSTRUMENTS 64
  29. #define MAX_ENVELOPES 128
  30. #define MAX_ENVELOPE_LEN 256
  31.  
  32. unsigned int keep_instruments = 0;                 // ** if != 0, don't remove any instruments
  33. unsigned char song_name[MAX_SUB_SONGS][256] = {0}; // **
  34.  
  35. struct channelStruct
  36. {
  37.     unsigned char note; //0 empty position, 1 rest note, 2 and above note starting from C-0
  38.     char instrument;    //0 no change, 1 and above instrument number
  39.     char effect;
  40.     unsigned char parameter;
  41.     signed char volume; // **
  42. };
  43.  
  44. struct rowStruct
  45. {
  46.     channelStruct channel[5];
  47.     unsigned char speed;
  48. };
  49.  
  50. struct patternStruct
  51. {
  52.     rowStruct row[MAX_ROWS];
  53.     unsigned char length;
  54. };
  55.  
  56. struct songStruct
  57. {
  58.     int speed;
  59.     int tempo;
  60.     int pattern_length;
  61.     int order_length;
  62.     int order_loop;
  63.  
  64.     patternStruct pattern[MAX_PATTERNS];
  65. };
  66.  
  67. struct instrumentStruct
  68. {
  69.     short int volume;
  70.     short int pitch;
  71.     short int arpeggio;
  72.     short int duty;
  73.     short int id;
  74.  
  75.     bool in_use;
  76. };
  77.  
  78. struct envelopeStruct
  79. {
  80.     short int value[MAX_ENVELOPE_LEN];
  81.     short int length;
  82.     short int loop;
  83.     short int out_id;
  84.  
  85.     bool in_use;
  86. };
  87.  
  88. struct dpcmEntryStruct
  89. {
  90.     int off;
  91.     int size;
  92. };
  93.  
  94. struct sampleStruct
  95. {
  96.     int off;
  97.     int size;
  98.     int pitch;
  99.     int loop;
  100.     int id;
  101. };
  102.  
  103. envelopeStruct envelopeVolume[MAX_ENVELOPES];
  104. envelopeStruct envelopeArpeggio[MAX_ENVELOPES];
  105. envelopeStruct envelopePitch[MAX_ENVELOPES];
  106. envelopeStruct envelopeDuty[MAX_ENVELOPES];
  107.  
  108. songStruct song_original;
  109. songStruct song_split;
  110.  
  111. instrumentStruct instruments[MAX_INSTRUMENTS];
  112. sampleStruct sample_list[MAX_INSTRUMENTS];
  113.  
  114. unsigned char dpcm[16384];
  115. int dpcm_size;
  116.  
  117. char *text_src = NULL;
  118. int text_size;
  119.  
  120. FILE *outfile = NULL;
  121.  
  122. struct outputEnvelopeStruct
  123. {
  124.     unsigned char data[MAX_ENVELOPE_LEN + 2];
  125.     int size;
  126. };
  127.  
  128. outputEnvelopeStruct outputEnvelopes[MAX_ENVELOPES * 4 + 1];
  129.  
  130. int outputEnvelopeCount;
  131.  
  132. int subSongsCount;
  133.  
  134. #define MAX_PACKED_ROWS 256
  135. #define MAX_PACKED_PATTERNS (5 * MAX_ORDER * MAX_SUB_SONGS)
  136. #define MAX_PACKED_SIZE MAX_PACKED_ROWS * 4
  137.  
  138. struct packedPatternStruct
  139. {
  140.     unsigned char data[MAX_PACKED_SIZE];
  141.     short int length;
  142.     short int ref_id;
  143.     short int ref_length;
  144. };
  145.  
  146. packedPatternStruct packedPatterns[MAX_PACKED_PATTERNS];
  147.  
  148. int packedCount;
  149. int referenceId;
  150.  
  151. int outtype;
  152.  
  153. int channels;
  154.  
  155. char songName[1024];
  156. char songName1[1024];
  157.  
  158. bool text_open(char *filename)
  159. {
  160.     FILE *file;
  161.     int ps, pd, size;
  162.     char *text;
  163.     char c;
  164.  
  165.     file = fopen(filename, "rb");
  166.  
  167.     if (!file)
  168.         return false;
  169.  
  170.     fseek(file, 0, SEEK_END);
  171.     size = ftell(file);
  172.     fseek(file, 0, SEEK_SET);
  173.  
  174.     text = (char *)malloc(size);
  175.  
  176.     fread(text, size, 1, file);
  177.     fclose(file);
  178.  
  179.     if (text_src)
  180.     {
  181.         free(text_src);
  182.         text_src = NULL;
  183.     }
  184.  
  185.     text_src = (char *)malloc(size + 1); //extra byte in case no 0x0d to remove in the source text somehow
  186.  
  187.     ps = 0;
  188.     pd = 0;
  189.  
  190.     while (ps < size)
  191.     {
  192.         c = text[ps++];
  193.  
  194.         if (c == '\t')
  195.             c = ' ';
  196.  
  197.         if (c != 0x0d)
  198.             text_src[pd++] = c;
  199.     }
  200.  
  201.     text_src[pd++] = 0x0a;
  202.  
  203.     text_size = pd;
  204.  
  205.     if (text)
  206.     {
  207.         free(text);
  208.         text = NULL;
  209.     }
  210.  
  211.     return true;
  212. }
  213.  
  214. void text_close(void)
  215. {
  216.     if (text_src)
  217.     {
  218.         free(text_src);
  219.         text_src = NULL;
  220.         text_size = 0;
  221.     }
  222. }
  223.  
  224. int text_skip_line(int off)
  225. {
  226.     while (off < text_size)
  227.     {
  228.         if (text_src[off++] == 0x0a)
  229.             break;
  230.     }
  231.  
  232.     return off;
  233. }
  234.  
  235. int text_skip_spaces(int off)
  236. {
  237.     while (off < text_size)
  238.         if (text_src[off] == ' ')
  239.             ++off;
  240.         else
  241.             break;
  242.  
  243.     return off;
  244. }
  245.  
  246. int text_skip_dec_and_spaces(int off)
  247. {
  248.     char n;
  249.  
  250.     off = text_skip_spaces(off);
  251.  
  252.     while (off < text_size)
  253.     {
  254.         n = text_src[off];
  255.  
  256.         if (!((n >= '0' && n <= '9') || n == '-'))
  257.             break;
  258.  
  259.         ++off;
  260.     }
  261.  
  262.     return text_skip_spaces(off);
  263. }
  264.  
  265. int text_skip_hex_and_spaces(int off)
  266. {
  267.     char n;
  268.  
  269.     off = text_skip_spaces(off);
  270.  
  271.     while (off < text_size)
  272.     {
  273.         n = text_src[off];
  274.  
  275.         if (!((n >= '0' && n <= '9') || (n >= 'a' && n <= 'f') || (n >= 'A' && n <= 'F')))
  276.             break;
  277.  
  278.         ++off;
  279.     }
  280.  
  281.     return text_skip_spaces(off);
  282. }
  283.  
  284. int text_find_tag(const char *tag, int off)
  285. {
  286.     int i;
  287.  
  288.     for (i = off; i < text_size - (int)strlen(tag); ++i)
  289.     {
  290.         if (!memcmp(&text_src[i], tag, strlen(tag)))
  291.             return text_skip_spaces(i + strlen(tag));
  292.     }
  293.  
  294.     return -1;
  295. }
  296.  
  297. int text_find_tag_start_sub_song(const char *tag, int off)
  298. {
  299.     int i;
  300.  
  301.     for (i = off; i < text_size - (int)strlen(tag); ++i)
  302.     {
  303.         if (!memcmp(&text_src[i], "TRACK", 5))
  304.             return -1;
  305.  
  306.         if (!memcmp(&text_src[i], tag, strlen(tag)))
  307.             return text_skip_spaces(i + strlen(tag));
  308.     }
  309.  
  310.     return -1;
  311. }
  312.  
  313. int text_skip_tag(int off)
  314. {
  315.     while (off < text_size)
  316.     {
  317.         if (text_src[off] <= ' ')
  318.             break;
  319.  
  320.         ++off;
  321.     }
  322.  
  323.     return text_skip_spaces(off);
  324. }
  325.  
  326. int text_find_tag_section(const char *tag, int off)
  327. {
  328.     while (off < text_size - (int)strlen(tag))
  329.     {
  330.         if (text_src[off] == '[')
  331.             break;
  332.  
  333.         if (!memcmp(&text_src[off], tag, strlen(tag)))
  334.             return text_skip_spaces(off + strlen(tag));
  335.  
  336.         ++off;
  337.     }
  338.  
  339.     return -1;
  340. }
  341.  
  342. int text_find_tag_start(const char *tag, int off)
  343. {
  344.     int i;
  345.  
  346.     for (i = off; i < text_size - (int)strlen(tag); ++i)
  347.     {
  348.         if (!memcmp(&text_src[i], tag, strlen(tag)))
  349.             return i;
  350.     }
  351.  
  352.     return -1;
  353. }
  354.  
  355. int text_read_dec(int off)
  356. {
  357.     int n, num, sign;
  358.  
  359.     num = 0;
  360.  
  361.     if (text_src[off] == '-')
  362.     {
  363.         ++off;
  364.         sign = -1;
  365.     }
  366.     else
  367.     {
  368.         sign = 1;
  369.     }
  370.  
  371.     while (off < text_size)
  372.     {
  373.         n = text_src[off++];
  374.  
  375.         if (n < '0' || n > '9')
  376.             break;
  377.  
  378.         num = num * 10 + n - '0';
  379.     }
  380.  
  381.     return num * sign;
  382. }
  383.  
  384. int hex(char c)
  385. {
  386.     if (c >= '0' && c <= '9')
  387.         return c - '0';
  388.     if (c >= 'A' && c <= 'F')
  389.         return c - 'A' + 10;
  390.     if (c >= 'a' && c <= 'f')
  391.         return c - 'a' + 10;
  392.  
  393.     return -1;
  394. }
  395.  
  396. int text_read_hex(int off)
  397. {
  398.     int n, num;
  399.  
  400.     num = 0;
  401.  
  402.     while (off < text_size)
  403.     {
  404.         n = hex(text_src[off++]);
  405.  
  406.         if (n < 0)
  407.             break;
  408.  
  409.         num = num * 16 + n;
  410.     }
  411.  
  412.     return num;
  413. }
  414.  
  415. void clear_packed_patterns(void)
  416. {
  417.     memset(packedPatterns, 0, sizeof(packedPatterns));
  418.  
  419.     packedCount = 0; //clear packed patterns list, it is common for all sub songs
  420.     referenceId = 0; //global reference id
  421. }
  422.  
  423. void clear_song(void)
  424. {
  425.     memset(&song_original, 0, sizeof(song_original));
  426. }
  427.  
  428. void clear_instruments(void)
  429. {
  430.     memset(&instruments, 0, sizeof(instruments));
  431.     memset(&envelopeVolume, 0, sizeof(envelopeVolume));
  432.     memset(&envelopeArpeggio, 0, sizeof(envelopeArpeggio));
  433.     memset(&envelopePitch, 0, sizeof(envelopePitch));
  434.     memset(&envelopeDuty, 0, sizeof(envelopeDuty));
  435.  
  436.     memset(dpcm, 0, sizeof(dpcm));
  437.  
  438.     dpcm_size = 0;
  439.  
  440.     memset(sample_list, 0, sizeof(sample_list));
  441.  
  442.     subSongsCount = 0;
  443. }
  444.  
  445. void parse_error(int off, const char *str)
  446. {
  447.     int ptr, row, col;
  448.  
  449.     if (off < 0)
  450.     {
  451.         printf("Parsing error: %s\n", str);
  452.     }
  453.     else
  454.     {
  455.         row = 1;
  456.         col = 1;
  457.         ptr = 0;
  458.  
  459.         while (ptr < off)
  460.         {
  461.             if (text_src[ptr++] == '\n')
  462.             {
  463.                 ++row;
  464.                 col = 0;
  465.             }
  466.  
  467.             ++col;
  468.         }
  469.  
  470.         printf("Parsing error (row %i,col %i): %s\n", row, col, str);
  471.     }
  472.  
  473.     exit(1);
  474. }
  475.  
  476. void parse_error_ptn(int song, int pos, int row, int chn, const char *str)
  477. {
  478.     printf("Parsing error (song:%2.2i pos:%2.2x row:%2.2x chn %i): %s\n", song + 1, pos, row, chn, str);
  479.  
  480.     exit(1);
  481. }
  482.  
  483. // void parse_instruments_old(void)
  484. // {
  485. // ** removed
  486. // }
  487.  
  488. // void parse_song_old(void)
  489. // {
  490. // ** removed
  491. // }
  492.  
  493. void parse_instruments(void)
  494. {
  495.     int i, n, off, ptr, id, type, loop, ins, octave, note, pitch, size, ins_id;
  496.     envelopeStruct *env;
  497.     static char str[1024];
  498.  
  499.     //check how many sub songs are there
  500.  
  501.     off = 0;
  502.     subSongsCount = 0;
  503.  
  504.     while (1)
  505.     {
  506.         off = text_find_tag("TRACK", off);
  507.  
  508.         if (off < 0)
  509.             break;
  510.  
  511.         ++subSongsCount;
  512.     }
  513.  
  514.     if (subSongsCount > MAX_SUB_SONGS)
  515.         parse_error(0, "Too many sub songs");
  516.  
  517.     //parse envelopes
  518.  
  519.     off = text_find_tag("# Macros", 0);
  520.  
  521.     if (off < 0)
  522.         parse_error(off, "Macros section not found");
  523.  
  524.     while (off < text_size)
  525.     {
  526.         off = text_find_tag("MACRO", off);
  527.  
  528.         if (off < 0)
  529.             break;
  530.  
  531.         type = text_read_dec(off); //macro group number
  532.  
  533.         off = text_skip_dec_and_spaces(off);
  534.  
  535.         id = text_read_dec(off); //macro id in a group
  536.  
  537.         if (id > MAX_ENVELOPES)
  538.             parse_error(off, "Macro number is too large");
  539.  
  540.         off = text_skip_dec_and_spaces(off);
  541.  
  542.         loop = text_read_dec(off); //envelope loop
  543.  
  544.         off = text_skip_dec_and_spaces(off);
  545.  
  546.         n = text_read_dec(off); //unknown parameter
  547.  
  548.         off = text_skip_dec_and_spaces(off);
  549.  
  550.         n = text_read_dec(off); //unknown parameter
  551.  
  552.         off = text_skip_dec_and_spaces(off);
  553.  
  554.         if (text_src[off] != ':')
  555.             parse_error(off, "Unexpected macro format");
  556.  
  557.         switch (type)
  558.         {
  559.         case 0:
  560.             env = &envelopeVolume[id];
  561.             break; //volume
  562.         case 1:
  563.             env = &envelopeArpeggio[id];
  564.             break; //arpeggio
  565.         case 2:
  566.             env = &envelopePitch[id];
  567.             break; //pitch
  568.         case 4:
  569.             env = &envelopeDuty[id];
  570.             break; //duty
  571.         default:
  572.             env = NULL;
  573.         }
  574.  
  575.         if (env)
  576.         {
  577.             off += 2;
  578.             ptr = 0;
  579.  
  580.             while (off < text_size)
  581.             {
  582.                 if (text_src[off] == '\n')
  583.                     break;
  584.  
  585.                 if (ptr >= MAX_ENVELOPE_LEN)
  586.                     parse_error(off, "Macro is too long");
  587.  
  588.                 env->value[ptr++] = text_read_dec(off);
  589.  
  590.                 off = text_skip_dec_and_spaces(off);
  591.             }
  592.  
  593.             env->length = ptr;
  594.             env->loop = loop;
  595.         }
  596.     }
  597.  
  598.     //parse instruments
  599.  
  600.     for (i = 0; i < MAX_INSTRUMENTS; ++i)
  601.         sample_list[i].id = -1;
  602.  
  603.     off = text_find_tag("# Instruments", off);
  604.  
  605.     if (off < 0)
  606.         parse_error(off, "Instruments section not found");
  607.  
  608.     ins_id = 0;
  609.  
  610.     while (off < text_size)
  611.     {
  612.         off = text_skip_line(off);
  613.  
  614.         if (!memcmp(&text_src[off], "INST2A03", 8))
  615.         {
  616.             off = text_skip_tag(off);
  617.  
  618.             ins = text_read_dec(off); //instrument number
  619.  
  620.             if (ins < 0 || ins >= MAX_INSTRUMENTS)
  621.                 parse_error(off, "Wrong instrument number");
  622.  
  623.             if (ins > 63)
  624.                 parse_error(off, "Only 64 instruments (0..63) supported");
  625.  
  626.             off = text_skip_dec_and_spaces(off);
  627.  
  628.             instruments[ins].volume = text_read_dec(off); //volume envelope id
  629.  
  630.             if (instruments[ins].volume < 0)
  631.             {
  632.                 sprintf(str, "Instrument %i does not have volume envelope", ins);
  633.                 parse_error(off, str);
  634.             }
  635.  
  636.             off = text_skip_dec_and_spaces(off);
  637.  
  638.             instruments[ins].arpeggio = text_read_dec(off); //arpeggio envelope id
  639.  
  640.             off = text_skip_dec_and_spaces(off);
  641.  
  642.             instruments[ins].pitch = text_read_dec(off); //pitch envelope id
  643.  
  644.             off = text_skip_dec_and_spaces(off);
  645.  
  646.             n = text_read_dec(off); //unused hi-pitch envelope id
  647.  
  648.             off = text_skip_dec_and_spaces(off);
  649.  
  650.             instruments[ins].duty = text_read_dec(off); //duty cycle envelope id
  651.  
  652.             instruments[ins].id = ins_id;
  653.  
  654.             if (keep_instruments)
  655.             {
  656.                 instruments[ins].in_use = true; // **
  657.             }
  658.  
  659.             ++ins_id;
  660.  
  661.             continue;
  662.         }
  663.  
  664.         if (!memcmp(&text_src[off], "KEYDPCM", 7))
  665.         {
  666.             off = text_skip_tag(off);
  667.  
  668.             ins = text_read_dec(off); //instrument number
  669.  
  670.             if (ins != 0)
  671.                 continue;
  672.  
  673.             off = text_skip_dec_and_spaces(off);
  674.  
  675.             octave = text_read_dec(off); //octave
  676.  
  677.             off = text_skip_dec_and_spaces(off);
  678.  
  679.             note = text_read_dec(off); //note
  680.  
  681.             if ((octave * 12 + note) < 1 * 12 || (octave * 12 + note) >= 6 * 12 + 3)
  682.                 parse_error(off, "DPCM samples could only be assigned to notes C-1..D-6");
  683.  
  684.             ins = (octave - 1) * 12 + note;
  685.  
  686.             off = text_skip_dec_and_spaces(off);
  687.  
  688.             id = text_read_dec(off); //sample number
  689.  
  690.             off = text_skip_dec_and_spaces(off);
  691.  
  692.             pitch = text_read_dec(off); //pitch
  693.  
  694.             off = text_skip_dec_and_spaces(off);
  695.  
  696.             loop = text_read_dec(off); //loop
  697.  
  698.             off = text_skip_dec_and_spaces(off);
  699.  
  700.             n = text_read_dec(off); //unknown
  701.  
  702.             off = text_skip_dec_and_spaces(off);
  703.  
  704.             n = text_read_dec(off); //unknown
  705.  
  706.             sample_list[ins].id = id;
  707.             sample_list[ins].loop = loop;
  708.             sample_list[ins].pitch = pitch;
  709.             sample_list[ins].size = 0;
  710.  
  711.             continue;
  712.         }
  713.  
  714.         break;
  715.     }
  716.  
  717.     //parse sample data
  718.  
  719.     ptr = 0;
  720.  
  721.     off = text_find_tag("# DPCM samples", off);
  722.  
  723.     while (off < text_size)
  724.     {
  725.         off = text_find_tag("DPCMDEF", off);
  726.  
  727.         if (off < 0)
  728.             break;
  729.  
  730.         id = text_read_dec(off);
  731.         note = -1;
  732.  
  733.         for (i = 0; i < MAX_INSTRUMENTS; ++i)
  734.         {
  735.             if (sample_list[i].id == id)
  736.             {
  737.                 note = i;
  738.                 break;
  739.             }
  740.         }
  741.  
  742.         if (note < 0)
  743.             continue;
  744.  
  745.         off = text_skip_dec_and_spaces(off);
  746.  
  747.         size = text_read_dec(off);
  748.  
  749.         for (i = 0; i < MAX_INSTRUMENTS; ++i)
  750.         {
  751.             if (sample_list[i].id == id)
  752.             {
  753.                 sample_list[i].off = ptr >> 6;
  754.                 sample_list[i].size = size >> 4;
  755.             }
  756.         }
  757.  
  758.         while (off < text_size)
  759.         {
  760.             off = text_skip_line(off);
  761.  
  762.             if (memcmp(&text_src[off], "DPCM :", 6))
  763.                 break;
  764.  
  765.             off += 7;
  766.  
  767.             while (off < text_size)
  768.             {
  769.                 if (text_src[off] == '\n')
  770.                     break;
  771.  
  772.                 n = text_read_hex(off);
  773.                 off = text_skip_hex_and_spaces(off);
  774.  
  775.                 dpcm[ptr++] = n;
  776.                 --size;
  777.             }
  778.         }
  779.  
  780.         if (size != 0)
  781.             parse_error(off, "Actual DPCM sample size does not match its definition");
  782.  
  783.         ptr = ((ptr >> 6) + 1) << 6;
  784.     }
  785.  
  786.     for (i = 0; i < MAX_INSTRUMENTS; ++i)
  787.         if (sample_list[i].off < 0)
  788.             sample_list[i].off = 0;
  789.  
  790.     dpcm_size = ptr;
  791. }
  792.  
  793. void parse_song(int subsong, bool header_only)
  794. {
  795.     static patternStruct pattern[MAX_PATTERNS];
  796.     static int order[MAX_ORDER][5];
  797.  
  798.     char str[128];
  799.     int i, n, row, pos, off, ptn, chn, note, ins, maxptn, off_prev, vol; // **;
  800.     channelStruct *nsrc, *ndst;
  801.  
  802.     if (subsong >= subSongsCount)
  803.         parse_error(0, "No sub song found");
  804.  
  805.     off = text_find_tag("# Tracks", 0);
  806.  
  807.     for (i = 0; i <= subsong; ++i)
  808.         off = text_find_tag("TRACK", off);
  809.  
  810.     if (off < 0)
  811.         parse_error(off, "Can't find track section");
  812.  
  813.     off = text_skip_spaces(off);
  814.  
  815.     song_original.pattern_length = text_read_dec(off);
  816.  
  817.     off = text_skip_dec_and_spaces(off);
  818.  
  819.     song_original.speed = text_read_dec(off);
  820.  
  821.     off = text_skip_dec_and_spaces(off);
  822.  
  823.     song_original.tempo = text_read_dec(off);
  824.  
  825.     for (int a = 0; a < 6; a++)
  826.     {
  827.         if (text_src[off] == '\"')
  828.             break;
  829.         off++;
  830.     }
  831.     off++;
  832.  
  833.     for (int a = 0; a < 256; a++)
  834.     {
  835.  
  836.         if (text_src[off] == '\"')
  837.         {
  838.             song_name[subsong][a] = 0;
  839.             break;
  840.         }
  841.         song_name[subsong][a] = text_src[off];
  842.         off++;
  843.     }
  844.  
  845.     if (header_only)
  846.         return;
  847.  
  848.     //parse order list
  849.  
  850.     pos = 0;
  851.     maxptn = 0;
  852.  
  853.     off = text_find_tag_start("ORDER", off);
  854.  
  855.     while (off < text_size)
  856.     {
  857.         if (text_src[off] != 'O')
  858.             break;
  859.  
  860.         order[pos][0] = text_read_hex(off + 11);
  861.         order[pos][1] = text_read_hex(off + 14);
  862.         order[pos][2] = text_read_hex(off + 17);
  863.         order[pos][3] = text_read_hex(off + 20);
  864.         order[pos][4] = text_read_hex(off + 23);
  865.  
  866.         for (chn = 0; chn < channels; ++chn)
  867.             if (order[pos][chn] > maxptn)
  868.                 maxptn = order[pos][chn];
  869.  
  870.         off = text_skip_line(off);
  871.  
  872.         ++pos;
  873.     }
  874.  
  875.     song_original.order_length = pos;
  876.  
  877.     //parse patterns
  878.  
  879.     ptn = 0;
  880.  
  881.     for (i = 0; i <= maxptn; ++i)
  882.     {
  883.         pattern[ptn].length = song_original.pattern_length;
  884.  
  885.         sprintf(str, "PATTERN %2.2X", i);
  886.  
  887.         off_prev = off;
  888.  
  889.         off = text_find_tag_start_sub_song(str, off);
  890.  
  891.         if (off < 0) //pattern not found, could be caused by the Famitracker cleanup, just skip it
  892.         {
  893.             off = off_prev;
  894.  
  895.             for (row = 0; row < song_original.pattern_length; ++row)
  896.             {
  897.                 for (chn = 0; chn < channels; ++chn)
  898.                 {
  899.                     pattern[ptn].row[row].channel[chn].note = 0;
  900.                     pattern[ptn].row[row].channel[chn].instrument = 0;
  901.                     pattern[ptn].row[row].channel[chn].effect = 0;
  902.                     pattern[ptn].row[row].channel[chn].parameter = 0;
  903.                     pattern[ptn].row[row].channel[chn].volume = 0; // **
  904.                 }
  905.             }
  906.  
  907.             ++ptn;
  908.  
  909.             continue;
  910.         }
  911.  
  912.         off = text_skip_line(off);
  913.  
  914.         for (row = 0; row < song_original.pattern_length; ++row)
  915.         {
  916.             if (memcmp(&text_src[off], "ROW", 3))
  917.             {
  918.                 printf("%i\n", row);
  919.                 parse_error(off, "No row definition found ");
  920.             }
  921.  
  922.             if (text_read_hex(off + 4) != row)
  923.                 parse_error(off, "Unexpected row number");
  924.  
  925.             for (chn = 0; chn < channels; ++chn)
  926.             {
  927.                 while (text_src[off++] != ':')
  928.                     ; //skip to a channel position, regardless of number of effect columns
  929.  
  930.                 ++off;
  931.  
  932.                 n = text_src[off];
  933.  
  934.                 if (chn != 3) //normal channels
  935.                 {
  936.                     switch (n)
  937.                     {
  938.                     case '.':
  939.                         note = 0;
  940.                         break;
  941.                     case '-':
  942.                         note = 1;
  943.                         break;
  944.                     case 'C':
  945.                         note = 2;
  946.                         break;
  947.                     case 'D':
  948.                         note = 4;
  949.                         break;
  950.                     case 'E':
  951.                         note = 6;
  952.                         break;
  953.                     case 'F':
  954.                         note = 7;
  955.                         break;
  956.                     case 'G':
  957.                         note = 9;
  958.                         break;
  959.                     case 'A':
  960.                         note = 11;
  961.                         break;
  962.                     case 'B':
  963.                         note = 13;
  964.                         break;
  965.                     default:
  966.                         parse_error(off, "Unexpected character in the note field");
  967.                     }
  968.  
  969.                     if (text_src[off + 1] == '#')
  970.                         ++note;
  971.  
  972.                     if ((text_read_dec(off + 2) == 0) && (note < 11) && (note > 1))
  973.                         note = 11; // ** if too low
  974.  
  975.                     if (note > 1)
  976.                     {
  977.                         note += 12 * text_read_dec(off + 2); //add octave
  978.  
  979.                         if ((chn == 4) && ((note > 76) || (note < 14)))
  980.                             parse_error(off, "DPCM note is out of supported range (C-1..D-6)");
  981.  
  982.                         note -= 9; // ** correct range
  983.                     }
  984.                 }
  985.                 else //noise channel has different note format
  986.                 {
  987.                     switch (n)
  988.                     {
  989.                     case '.':
  990.                         note = 0;
  991.                         break;
  992.                     case '-':
  993.                         note = 1;
  994.                         break;
  995.                     default:
  996.                         n = hex(n);
  997.  
  998.                         if (n >= 0)
  999.                             note = ((n + 15) & 15) + 2;
  1000.                         else
  1001.                             parse_error(off, "Unexpected character in the note field");
  1002.                     }
  1003.                 }
  1004.  
  1005.                 if (text_src[off + 4] == '.')
  1006.                     ins = -1;
  1007.                 else
  1008.                     ins = text_read_hex(off + 4);
  1009.  
  1010.                 if (ins > 63)
  1011.                     parse_error(off, "Instrument number is out of range (0..63)");
  1012.  
  1013.                 if (text_src[off + 7] == '.')
  1014.                     vol = -1;
  1015.                 else
  1016.                     vol = text_read_hex(off + 7); // **
  1017.  
  1018.                 pattern[ptn].row[row].channel[chn].note = note;
  1019.                 pattern[ptn].row[row].channel[chn].instrument = ins;
  1020.                 pattern[ptn].row[row].channel[chn].effect = text_src[off + 9];
  1021.                 pattern[ptn].row[row].channel[chn].parameter = text_read_hex(off + 10);
  1022.                 pattern[ptn].row[row].channel[chn].volume = vol; // **
  1023.  
  1024.                 if (ins >= 0)
  1025.                     instruments[ins].in_use = true;
  1026.             }
  1027.  
  1028.             off = text_skip_line(off);
  1029.         }
  1030.  
  1031.         ++ptn;
  1032.     }
  1033.  
  1034.     //convert order list and patterns into song, reordering patterns in a linear order
  1035.  
  1036.     for (pos = 0; pos < song_original.order_length; ++pos)
  1037.     {
  1038.         song_original.pattern[pos].length = song_original.pattern_length;
  1039.  
  1040.         for (chn = 0; chn < channels; ++chn)
  1041.         {
  1042.             for (row = 0; row < song_original.pattern_length; ++row)
  1043.             {
  1044.                 nsrc = &pattern[order[pos][chn]].row[row].channel[chn];
  1045.                 ndst = &song_original.pattern[pos].row[row].channel[chn];
  1046.  
  1047.                 ndst->note = nsrc->note;
  1048.                 ndst->instrument = nsrc->instrument;
  1049.                 ndst->volume = nsrc->volume; // **
  1050.  
  1051.                 switch (nsrc->effect) //supported effects
  1052.                 {
  1053.                 case 0:
  1054.                 case '.':
  1055.                     break; //no effect
  1056.  
  1057.                 case 'B': //end song and loop to a provided order list position
  1058.                 {
  1059.                     song_original.order_length = pos + 1;
  1060.                     song_original.order_loop = nsrc->parameter;
  1061.  
  1062.                     song_original.pattern[pos].length = row + 1;
  1063.  
  1064.                     row = MAX_ROWS; //stop parsing current pattern
  1065.  
  1066.                     if (song_original.order_loop > pos)
  1067.                         parse_error_ptn(subsong, pos, row, chn, "Bxx loop position can't be a forward reference");
  1068.                 }
  1069.                 break;
  1070.  
  1071.                 case 'D': //end pattern early
  1072.                 {
  1073.                     song_original.pattern[pos].length = row + 1;
  1074.  
  1075.                     row = MAX_ROWS; //stop parsing current pattern
  1076.  
  1077.                     if (nsrc->parameter)
  1078.                         parse_error_ptn(subsong, pos, row, chn, "Dxx value can only be zero");
  1079.                 }
  1080.                 break;
  1081.  
  1082.                 case 'F': //change speed
  1083.                 {
  1084.                     song_original.pattern[pos].row[row].speed = nsrc->parameter;
  1085.                 }
  1086.                 break;
  1087.  
  1088.                 default:
  1089.                 {
  1090.                     printf("%c", nsrc->effect);
  1091.                     parse_error_ptn(subsong, pos, row, chn, "Unsupported effect");
  1092.                 }
  1093.                 }
  1094.             }
  1095.         }
  1096.     }
  1097. }
  1098.  
  1099. //remove repeating instrument numbers and repeating speed values
  1100.  
  1101. void song_cleanup_instrument_numbers(void)
  1102. {
  1103.     int chn, pos, row, ins, speed;
  1104.     channelStruct *ch;
  1105.     int insloop[5];
  1106.     bool stop;
  1107.  
  1108.     for (chn = 0; chn < channels; ++chn)
  1109.         insloop[chn] = -1;
  1110.  
  1111.     for (chn = 0; chn < channels; ++chn)
  1112.     {
  1113.         ins = -1;
  1114.         speed = 0;
  1115.  
  1116.         for (pos = 0; pos < song_original.order_length; ++pos)
  1117.         {
  1118.             for (row = 0; row < song_original.pattern[pos].length; ++row)
  1119.             {
  1120.                 ch = &song_original.pattern[pos].row[row].channel[chn];
  1121.  
  1122.                 if (chn < 4) //pulse, triangle, and noise channels
  1123.                 {
  1124.                     if (ch->note < 1 && ch->instrument >= 0)
  1125.                         ch->instrument = -1; //ignore instrument numbers at empty rows and rest notes
  1126.                                              // ** changed from note < 2
  1127.  
  1128.                     if (ch->instrument >= 0)
  1129.                     {
  1130.                         if (ins != ch->instrument)
  1131.                         {
  1132.                             ins = ch->instrument;
  1133.                         }
  1134.                         else
  1135.                         {
  1136.                             ch->instrument = -1;
  1137.                         }
  1138.                     }
  1139.                 }
  1140.                 else //dpcm channel
  1141.                 {
  1142.                     ch->instrument = -1;
  1143.                 }
  1144.  
  1145.                 if (!chn)
  1146.                 {
  1147.                     if (song_original.pattern[pos].row[row].speed)
  1148.                     {
  1149.                         if (speed == song_original.pattern[pos].row[row].speed)
  1150.                         {
  1151.                             song_original.pattern[pos].row[row].speed = 0;
  1152.                         }
  1153.                         else
  1154.                         {
  1155.                             speed = song_original.pattern[pos].row[row].speed;
  1156.                         }
  1157.                     }
  1158.                 }
  1159.             }
  1160.         }
  1161.  
  1162.         if (ins < 0)
  1163.             ins = 0;
  1164.  
  1165.         if (chn < 4)
  1166.             insloop[chn] = ins;
  1167.     }
  1168.  
  1169.     //set current instrument number for first actual note after the loop point
  1170.  
  1171.     for (chn = 0; chn < 4; ++chn)
  1172.     {
  1173.         if (insloop[chn] < 0)
  1174.             continue;
  1175.  
  1176.         stop = false;
  1177.  
  1178.         for (pos = song_original.order_loop; pos < song_original.order_length; ++pos)
  1179.         {
  1180.             for (row = 0; row < song_original.pattern[pos].length; ++row)
  1181.             {
  1182.                 ch = &song_original.pattern[pos].row[row].channel[chn];
  1183.  
  1184.                 if (ch->note >= 1) // **
  1185.                 {
  1186.                     if (ch->instrument < 0)
  1187.                         ch->instrument = insloop[chn];
  1188.  
  1189.                     stop = true;
  1190.                     break;
  1191.                 }
  1192.             }
  1193.  
  1194.             if (stop)
  1195.                 break;
  1196.         }
  1197.     }
  1198.  
  1199.     if (!song_original.pattern[song_original.order_loop].row[0].speed)
  1200.         song_original.pattern[song_original.order_loop].row[0].speed = speed;
  1201. }
  1202.  
  1203. //remove extra trailing zeroes in volume envelopes, cut duty cycle envelopes length
  1204.  
  1205. void envelopes_cleanup(void)
  1206. {
  1207.     int i, j;
  1208.  
  1209.     for (i = 0; i < MAX_ENVELOPES; ++i)
  1210.     {
  1211.         if (envelopeVolume[i].loop < 0)
  1212.         {
  1213.             for (j = envelopeVolume[i].length - 1; j > 0; --j)
  1214.                 if (!envelopeVolume[i].value[j] && !envelopeVolume[i].value[j - 1])
  1215.                     --envelopeVolume[i].length;
  1216.                 else
  1217.                     break;
  1218.         }
  1219.  
  1220.         if (envelopeDuty[i].length > 1)
  1221.             envelopeDuty[i].length = 1;
  1222.     }
  1223. }
  1224.  
  1225. //change pitch envelopes from absolute to accumulated value
  1226.  
  1227. void envelope_pitch_convert(void)
  1228. {
  1229.     int i, j, val;
  1230.  
  1231.     for (i = 0; i < MAX_ENVELOPES; ++i)
  1232.     {
  1233.         val = 0;
  1234.  
  1235.         for (j = 0; j < envelopePitch[i].length; ++j)
  1236.         {
  1237.             val += envelopePitch[i].value[j];
  1238.  
  1239.             if (val < -64)
  1240.                 val = -64;
  1241.             if (val > 63)
  1242.                 val = 63;
  1243.  
  1244.             envelopePitch[i].value[j] = val;
  1245.         }
  1246.     }
  1247. }
  1248.  
  1249. // void song_text_dump(songStruct *s)
  1250. // {
  1251. // ** removed
  1252. // }
  1253.  
  1254. void output_open(const char *filename)
  1255. {
  1256.     outfile = fopen(filename, "wt");
  1257. }
  1258.  
  1259. int output_dump_byte_array(unsigned char *data, int length, bool test)
  1260. {
  1261.     int col, ptr;
  1262.  
  1263.     if (test)
  1264.         return length;
  1265.  
  1266.     ptr = 0;
  1267.     col = 0;
  1268.  
  1269.     while (ptr < length)
  1270.     {
  1271.         if (!col)
  1272.             fprintf(outfile, "\t%s ", DB);
  1273.  
  1274.         fprintf(outfile, "$%2.2x", data[ptr++]);
  1275.  
  1276.         ++col;
  1277.  
  1278.         if (col >= 16 || ptr == length)
  1279.         {
  1280.             fprintf(outfile, "\n");
  1281.             col = 0;
  1282.         }
  1283.         else
  1284.         {
  1285.             fprintf(outfile, ",");
  1286.         }
  1287.     }
  1288.  
  1289.     return length;
  1290. }
  1291.  
  1292. int output_process_envelope(short int *value, int length, int loop)
  1293. {
  1294.     static unsigned char data[MAX_ENVELOPE_LEN];
  1295.     int i, j, val, prev_val, rle_cnt, ptr, ptr_loop, size;
  1296.  
  1297.     if (length <= 0)
  1298.         return 0; //default envelope
  1299.  
  1300.     ptr = 0;
  1301.     ptr_loop = -1;
  1302.  
  1303.     prev_val = value[0] + 1; //prevent rle match
  1304.     rle_cnt = 0;
  1305.  
  1306.     for (j = 0; j < length; ++j)
  1307.     {
  1308.         if (j == loop)
  1309.             ptr_loop = ptr;
  1310.  
  1311.         val = value[j];
  1312.  
  1313.         if (val < -64)
  1314.             val = -64;
  1315.         if (val > 63)
  1316.             val = 63;
  1317.  
  1318.         val += 192;
  1319.  
  1320.         if (prev_val != val || j == length - 1)
  1321.         {
  1322.             if (rle_cnt)
  1323.             {
  1324.                 if (rle_cnt == 1)
  1325.                 {
  1326.                     data[ptr++] = prev_val;
  1327.                 }
  1328.                 else
  1329.                 {
  1330.                     while (rle_cnt > 126)
  1331.                     {
  1332.                         data[ptr++] = 126;
  1333.                         rle_cnt -= 126;
  1334.                     }
  1335.  
  1336.                     data[ptr++] = rle_cnt;
  1337.                 }
  1338.  
  1339.                 rle_cnt = 0;
  1340.             }
  1341.  
  1342.             data[ptr++] = val;
  1343.  
  1344.             prev_val = val;
  1345.         }
  1346.         else
  1347.         {
  1348.             ++rle_cnt;
  1349.         }
  1350.     }
  1351.  
  1352.     if (ptr_loop < 0)
  1353.         ptr_loop = ptr - 1;
  1354.     else if (data[ptr_loop] < 128)
  1355.         ++ptr_loop; //ptr_loop increased if it points at RLEd repeats of a previous value
  1356.  
  1357.     data[ptr++] = 0;
  1358.     data[ptr++] = ptr_loop;
  1359.  
  1360.     size = ptr;
  1361.  
  1362.     for (i = 0; i < outputEnvelopeCount; ++i)
  1363.     {
  1364.         if (!memcmp(outputEnvelopes[i].data, data, size))
  1365.             return i;
  1366.     }
  1367.  
  1368.     memcpy(outputEnvelopes[outputEnvelopeCount].data, data, size);
  1369.  
  1370.     outputEnvelopes[outputEnvelopeCount].size = size;
  1371.  
  1372.     ++outputEnvelopeCount;
  1373.  
  1374.     return outputEnvelopeCount - 1;
  1375. }
  1376.  
  1377. int output_header(char *songname, int song)
  1378. {
  1379.     int sub, chn, tempo_pal, tempo_ntsc, size, from, to;
  1380.  
  1381.     fprintf(outfile, ";this file for FamiTone3.2 library generated by text2vol tool\n");
  1382.     fprintf(outfile, ";edited by Doug Fraker, 2016-7, to add volume column, all notes\n\n"); // **
  1383.  
  1384.     fprintf(outfile, "%s_music_data:\n", songname);
  1385.     fprintf(outfile, "\t%s %i\n", DB, subSongsCount);
  1386.     fprintf(outfile, "\t%s %sinstruments\n", DW, LL);
  1387.     fprintf(outfile, "\t%s %ssamples-3\n", DW, LL);
  1388.  
  1389.     size = 5;
  1390.  
  1391.     if (song < 0)
  1392.     {
  1393.         from = 0;
  1394.         to = subSongsCount;
  1395.     }
  1396.     else
  1397.     {
  1398.         from = song;
  1399.         to = from + 1;
  1400.     }
  1401.     for (sub = from; sub < to; ++sub)
  1402.     {
  1403.         parse_song(sub, true);
  1404.  
  1405.         fprintf(outfile, "\t%s ", DW);
  1406.  
  1407.         for (chn = 0; chn < 5; ++chn)
  1408.         {
  1409.             if (chn < channels)
  1410.                 fprintf(outfile, "%ssong%ich%i,", LL, sub, chn);
  1411.             else
  1412.                 fprintf(outfile, "0,");
  1413.         }
  1414.  
  1415.         tempo_pal = 256 * song_original.tempo / (50 * 60 / 24);
  1416.         tempo_ntsc = 256 * song_original.tempo / (60 * 60 / 24);
  1417.  
  1418.         fprintf(outfile, "%i,%i ; ", tempo_pal, tempo_ntsc);
  1419.  
  1420.         for (int a = 0; a < 256; a++)
  1421.         {
  1422.             if (song_name[sub][a] == 0)
  1423.                 break;
  1424.             fprintf(outfile, "%c", song_name[sub][a]);
  1425.         }
  1426.         fprintf(outfile, "\n");
  1427.  
  1428.         size += 14;
  1429.     }
  1430.  
  1431.     fprintf(outfile, "\n");
  1432.  
  1433.     return size;
  1434. }
  1435.  
  1436. int output_instruments(void)
  1437. {
  1438.     int i, size, duty;
  1439.  
  1440.     size = 0;
  1441.  
  1442.     //add default envelope, used for any undefined envelopes, it simply keeps 0
  1443.  
  1444.     outputEnvelopeCount = 0;
  1445.  
  1446.     outputEnvelopes[outputEnvelopeCount].data[0] = 0xc0;
  1447.     outputEnvelopes[outputEnvelopeCount].data[1] = 0x00;
  1448.     outputEnvelopes[outputEnvelopeCount].data[2] = 0x00;
  1449.     outputEnvelopes[outputEnvelopeCount].size = 3;
  1450.  
  1451.     ++outputEnvelopeCount;
  1452.  
  1453.     //mark all used envelopes
  1454.  
  1455.     for (i = 0; i < MAX_ENVELOPES; ++i)
  1456.     {
  1457.         envelopeVolume[i].in_use = false;
  1458.         envelopeArpeggio[i].in_use = false;
  1459.         envelopePitch[i].in_use = false;
  1460.     }
  1461.  
  1462.     for (i = 0; i < MAX_INSTRUMENTS; ++i)
  1463.     {
  1464.         if (!instruments[i].in_use)
  1465.             continue;
  1466.  
  1467.         envelopeVolume[instruments[i].volume].in_use = true;
  1468.         envelopeArpeggio[instruments[i].arpeggio].in_use = true;
  1469.         envelopePitch[instruments[i].pitch].in_use = true;
  1470.     }
  1471.  
  1472.     //convert all envelopes into byte data, add into common list, remove duplicates
  1473.  
  1474.     for (i = 0; i < MAX_ENVELOPES; ++i)
  1475.         envelopeVolume[i].out_id = output_process_envelope(envelopeVolume[i].value, envelopeVolume[i].in_use ? envelopeVolume[i].length : 0, envelopeVolume[i].loop);
  1476.     for (i = 0; i < MAX_ENVELOPES; ++i)
  1477.         envelopeArpeggio[i].out_id = output_process_envelope(envelopeArpeggio[i].value, envelopeArpeggio[i].in_use ? envelopeArpeggio[i].length : 0, envelopeArpeggio[i].loop);
  1478.     for (i = 0; i < MAX_ENVELOPES; ++i)
  1479.         envelopePitch[i].out_id = output_process_envelope(envelopePitch[i].value, envelopePitch[i].in_use ? envelopePitch[i].length : 0, envelopePitch[i].loop);
  1480.  
  1481.     //output instrument list
  1482.  
  1483.     fprintf(outfile, "%sinstruments:\n", LL);
  1484.  
  1485.     for (i = 0; i < MAX_INSTRUMENTS; ++i)
  1486.     {
  1487.         if (!instruments[i].in_use)
  1488.             continue;
  1489.  
  1490.         if (envelopeDuty[instruments[i].duty].length > 0)
  1491.             duty = envelopeDuty[instruments[i].duty].value[0] & 3;
  1492.         else
  1493.             duty = 0;
  1494.  
  1495.         fprintf(outfile, "\t%s $%2.2x ;instrument $%2.2x\n", DB, (duty << 6) | 0x30, i);
  1496.         fprintf(outfile, "\t%s ", DW);
  1497.         fprintf(outfile, "%senv%i,", LL, envelopeVolume[instruments[i].volume].out_id);
  1498.         fprintf(outfile, "%senv%i,", LL, envelopeArpeggio[instruments[i].arpeggio].out_id);
  1499.         fprintf(outfile, "%senv%i\n", LL, envelopePitch[instruments[i].pitch].out_id);
  1500.         fprintf(outfile, "\t%s $00\n", DB);
  1501.  
  1502.         size += 2 * 3 + 2;
  1503.     }
  1504.  
  1505.     fprintf(outfile, "\n");
  1506.  
  1507.     //output samples list
  1508.  
  1509.     fprintf(outfile, "%ssamples:\n", LL);
  1510.  
  1511.     if (dpcm_size)
  1512.     {
  1513.         for (i = 0; i < 63; ++i)
  1514.         {
  1515.             fprintf(outfile, "\t%s $%2.2x+%s(FT_DPCM_PTR),$%2.2x,$%2.2x\t;%i\n", DB, sample_list[i].off, LOW, sample_list[i].size, sample_list[i].pitch | ((sample_list[i].loop & 1) << 6), i + 1);
  1516.             size += 3;
  1517.         }
  1518.  
  1519.         fprintf(outfile, "\n");
  1520.     }
  1521.  
  1522.     //output envelope data
  1523.  
  1524.     for (i = 0; i < outputEnvelopeCount; ++i)
  1525.     {
  1526.         fprintf(outfile, "%senv%i:\n", LL, i);
  1527.  
  1528.         size += output_dump_byte_array(outputEnvelopes[i].data, outputEnvelopes[i].size, false);
  1529.     }
  1530.  
  1531.     return size;
  1532. }
  1533.  
  1534. int output_song(int sub, int spdchn, bool test)
  1535. {
  1536.     static int ins_renumber[MAX_INSTRUMENTS];
  1537.     int i, ins, chn, srow, pos, ptr, note, size, ref, pcnt, pref, len, n1, n2, nrow, empty, ref_len, vol; // **
  1538.     static packedPatternStruct tptn;
  1539.     rowStruct *row;
  1540.     patternStruct *ptn;
  1541.  
  1542.     //prepare instrument renumbering list
  1543.  
  1544.     ins = 0;
  1545.  
  1546.     for (i = 0; i < MAX_INSTRUMENTS; ++i)
  1547.     {
  1548.         if (instruments[i].in_use)
  1549.         {
  1550.             ins_renumber[i] = ins;
  1551.             ++ins;
  1552.         }
  1553.         else
  1554.         {
  1555.             ins_renumber[i] = 0;
  1556.         }
  1557.     }
  1558.  
  1559.     //process song data
  1560.  
  1561.     pcnt = packedCount;
  1562.     pref = referenceId;
  1563.  
  1564.     size = 0;
  1565.  
  1566.     if (!test)
  1567.         fprintf(outfile, "\n");
  1568.  
  1569.     for (chn = 0; chn < channels; ++chn)
  1570.     {
  1571.         if (!test)
  1572.         {
  1573.             fprintf(outfile, "\n; ");
  1574.  
  1575.             for (int a = 0; a < 256; a++)
  1576.             {
  1577.                 if (song_name[sub][a] == 0)
  1578.                     break;
  1579.                 fprintf(outfile, "%c", song_name[sub][a]);
  1580.             }
  1581.             fprintf(outfile, "\n");
  1582.  
  1583.             fprintf(outfile, "%ssong%ich%i:\n", LL, sub, chn);
  1584.         }
  1585.  
  1586.         if (chn == spdchn) //default speed
  1587.         {
  1588.             ptr = 0;
  1589.  
  1590.             tptn.data[ptr++] = 0xfb;
  1591.             tptn.data[ptr++] = song_split.speed;
  1592.  
  1593.             tptn.length = ptr;
  1594.  
  1595.             size += output_dump_byte_array(tptn.data, tptn.length, test);
  1596.         }
  1597.  
  1598.         for (pos = 0; pos < song_split.order_length; ++pos)
  1599.         {
  1600.             if (!test && pos == song_split.order_loop)
  1601.                 fprintf(outfile, "%ssong%ich%iloop:\n", LL, sub, chn);
  1602.  
  1603.             ptr = 0;
  1604.  
  1605.             ptn = &song_split.pattern[pos];
  1606.  
  1607.             //convert a single pattern
  1608.  
  1609.             len = song_split.pattern[pos].length;
  1610.             srow = 0;
  1611.             ref_len = len; //pattern length without repeating empty rows
  1612.  
  1613.             while (srow < len)
  1614.             {
  1615.                 if (ptr >= MAX_PACKED_SIZE)
  1616.                     parse_error(0, "Not enough room in the tptn array");
  1617.  
  1618.                 row = &ptn->row[srow++];
  1619.  
  1620.                 note = row->channel[chn].note;
  1621.  
  1622.                 if (chn == spdchn && row->speed) //speed change
  1623.                 {
  1624.                     tptn.data[ptr++] = 0xfb;
  1625.                     tptn.data[ptr++] = row->speed;
  1626.                 }
  1627.  
  1628.                 vol = row->channel[chn].volume; // **
  1629.                 if ((vol >= 0) && ((chn < 2) || (chn == 3)))
  1630.                 {
  1631.                     tptn.data[ptr++] = 0x70 | vol; // **
  1632.                 }
  1633.  
  1634.                 if (note > 0)
  1635.                 {
  1636.                     //check if there is instrument change
  1637.  
  1638.                     ins = row->channel[chn].instrument;
  1639.  
  1640.                     if (ins >= 0)
  1641.                         tptn.data[ptr++] = 0x80 | (ins_renumber[ins] << 1);
  1642.  
  1643.                     // **
  1644.                     //check if the note is followed by an empty row followed by a note
  1645.  
  1646.                     /*n1 = 0;
  1647.                     n2 = 0;
  1648.  
  1649.                     if (srow + 0<len)
  1650.                     {
  1651.                     n1 = ptn->row[srow + 0].channel[chn].note;
  1652.  
  1653.                     if (chn == spdchn&&ptn->row[srow + 0].speed) n1 = 1;
  1654.                     }
  1655.  
  1656.                     if (srow + 1<len)
  1657.                     {
  1658.                     n2 = ptn->row[srow + 1].channel[chn].note;
  1659.  
  1660.                     if (chn == spdchn&&ptn->row[srow + 1].speed) n2 = 1;
  1661.                     }*/
  1662.  
  1663.                     //nrow = (!n1&&n2) ? 0x01 : 0x00;//next empty row flag
  1664.  
  1665.                     if (chn == 4)
  1666.                         note -= 3;
  1667.  
  1668.                     tptn.data[ptr++] = note - 1; // ** 0 rest note, 1..60 are octaves 1-5
  1669.  
  1670.                     /*if (nrow)
  1671.                                                  {
  1672.                                                  ++srow;
  1673.                                                  --ref_len;
  1674.                                                  }*/
  1675.  
  1676.                     continue;
  1677.                 }
  1678.  
  1679.                 //count how many empty lines are there
  1680.  
  1681.                 empty = 0;
  1682.  
  1683.                 while (srow < len)
  1684.                 {
  1685.                     if (empty >= MAX_REPEAT_CNT)
  1686.                         break;
  1687.                     if (ptn->row[srow].channel[chn].note)
  1688.                         break;
  1689.                     if (chn == spdchn && ptn->row[srow].speed)
  1690.                         break;
  1691.                     if (ptn->row[srow].channel[chn].volume >= 0)
  1692.                         break; // **
  1693.  
  1694.                     ++srow;
  1695.                     ++empty;
  1696.                 }
  1697.  
  1698.                 ref_len -= empty;
  1699.  
  1700.                 tptn.data[ptr++] = 0x81 | (empty << 1);
  1701.             }
  1702.  
  1703.             tptn.length = ptr;
  1704.             tptn.ref_length = ref_len;
  1705.  
  1706.             //search for data match in the common data list
  1707.  
  1708.             ref = -1;
  1709.  
  1710.             if (tptn.length > 4) //search data matches longer than the reference itself
  1711.             {
  1712.                 for (i = 0; i < packedCount; ++i)
  1713.                 {
  1714.                     if (tptn.length <= packedPatterns[i].length)
  1715.                     {
  1716.                         if (!memcmp(tptn.data, packedPatterns[i].data, tptn.length)) //match found
  1717.                         {
  1718.                             ref = i;
  1719.                             break;
  1720.                         }
  1721.                     }
  1722.                 }
  1723.             }
  1724.  
  1725.             if (ref < 0) //no match found, put data into output and the common data list
  1726.             {
  1727.                 if (packedCount >= MAX_PACKED_PATTERNS)
  1728.                     parse_error(0, "Not enough room in the common data list");
  1729.  
  1730.                 memcpy(packedPatterns[packedCount].data, tptn.data, tptn.length);
  1731.  
  1732.                 packedPatterns[packedCount].length = tptn.length;
  1733.                 packedPatterns[packedCount].ref_length = tptn.ref_length;
  1734.                 packedPatterns[packedCount].ref_id = referenceId;
  1735.  
  1736.                 ++packedCount;
  1737.  
  1738.                 if (!test)
  1739.                     fprintf(outfile, "%sref%i:\n", LL, referenceId);
  1740.  
  1741.                 size += output_dump_byte_array(tptn.data, tptn.length, test);
  1742.             }
  1743.             else //match found, put reference into output
  1744.             {
  1745.                 if (!test)
  1746.                 {
  1747.                     fprintf(outfile, "\t%s $ff,$%2.2x\n", DB, ref_len);
  1748.                     fprintf(outfile, "\t%s %sref%i\n", DW, LL, packedPatterns[ref].ref_id);
  1749.                 }
  1750.  
  1751.                 size += 4;
  1752.             }
  1753.  
  1754.             ++referenceId;
  1755.         }
  1756.  
  1757.         if (!test)
  1758.         {
  1759.             fprintf(outfile, "\t%s $fd\n", DB); //end of stream
  1760.             fprintf(outfile, "\t%s %ssong%ich%iloop\n", DW, LL, sub, chn);
  1761.         }
  1762.  
  1763.         size += 3;
  1764.     }
  1765.  
  1766.     if (test) //not add packed patterns into the common list in test mode
  1767.     {
  1768.         packedCount = pcnt;
  1769.         referenceId = pref;
  1770.     }
  1771.  
  1772.     return size;
  1773. }
  1774.  
  1775. void output_close(void)
  1776. {
  1777.     if (outfile)
  1778.     {
  1779.         fclose(outfile);
  1780.         outfile = NULL;
  1781.     }
  1782. }
  1783.  
  1784. //split songs into shorter patterns by dividing pattern lengths by the factor
  1785.  
  1786. void split_song(int factor)
  1787. {
  1788.     int spos, srow, dpos, drow, nlen, cnt;
  1789.  
  1790.     //check if all patterns are shorter than the minimal length after split
  1791.  
  1792.     cnt = 0;
  1793.  
  1794.     for (spos = 0; spos < song_original.order_length; ++spos)
  1795.         if (song_original.pattern[spos].length / factor < MIN_PATTERN_LEN)
  1796.             ++cnt;
  1797.  
  1798.     if (cnt == song_original.order_length)
  1799.         factor = 1; //don't do split in this case, to make optimal split search faster
  1800.  
  1801.     //split patterns
  1802.  
  1803.     memset(&song_split, 0, sizeof(song_split));
  1804.  
  1805.     song_split.speed = song_original.speed;
  1806.     song_split.tempo = song_original.tempo;
  1807.  
  1808.     dpos = 0;
  1809.  
  1810.     for (spos = 0; spos < song_original.order_length; ++spos)
  1811.     {
  1812.         if (spos == song_original.order_loop)
  1813.             song_split.order_loop = dpos;
  1814.  
  1815.         nlen = song_original.pattern[spos].length / factor;
  1816.  
  1817.         if (nlen < MIN_PATTERN_LEN)
  1818.             nlen = MIN_PATTERN_LEN;
  1819.  
  1820.         drow = 0;
  1821.  
  1822.         for (srow = 0; srow < song_original.pattern[spos].length; ++srow)
  1823.         {
  1824.             memcpy(&song_split.pattern[dpos].row[drow], &song_original.pattern[spos].row[srow], sizeof(rowStruct));
  1825.  
  1826.             song_split.pattern[dpos].row[drow].speed = song_original.pattern[spos].row[srow].speed;
  1827.  
  1828.             ++drow;
  1829.  
  1830.             if (drow >= nlen || srow == song_original.pattern[spos].length - 1)
  1831.             {
  1832.                 song_split.pattern[dpos].length = drow;
  1833.  
  1834.                 ++dpos;
  1835.  
  1836.                 if (dpos >= MAX_PATTERNS)
  1837.                     parse_error(0, "Patterns array is not large enough");
  1838.  
  1839.                 drow = 0;
  1840.             }
  1841.         }
  1842.     }
  1843.  
  1844.     song_split.order_length = dpos;
  1845. }
  1846.  
  1847. //find best conversion settings and proceed with output
  1848.  
  1849. int process_and_output_song(int sub)
  1850. {
  1851.     int size, spdchn, factor, size_min, best_channel, best_factor;
  1852.  
  1853.     size_min = 65536;
  1854.     best_channel = 0;
  1855.     best_factor = 1;
  1856.  
  1857.     for (spdchn = 0; spdchn < channels; ++spdchn)
  1858.     {
  1859.         for (factor = 1; factor <= song_original.pattern_length / MIN_PATTERN_LEN; ++factor)
  1860.         {
  1861.             split_song(factor);
  1862.  
  1863.             size = output_song(sub, spdchn, true);
  1864.  
  1865.             if (size < size_min)
  1866.             {
  1867.                 size_min = size;
  1868.                 best_channel = spdchn;
  1869.                 best_factor = factor;
  1870.             }
  1871.         }
  1872.     }
  1873.  
  1874.     split_song(best_factor);
  1875.  
  1876.     //song_text_dump(&song_split);
  1877.  
  1878.     return output_song(sub, best_channel, false);
  1879. }
  1880.  
  1881. void exit_proc(void)
  1882. {
  1883.     //_getch();
  1884.     text_close();
  1885.     output_close();
  1886. }
  1887.  
  1888. int main(int argc, char *argv[])
  1889. {
  1890.     FILE *file;
  1891.     char inname[1024], outname[1024], outname1[1024], dpcmname[1024];
  1892.     int i, size_header, size_instruments, size_song[MAX_SUB_SONGS], size_total, sub;
  1893.     char c;
  1894.     bool separate;
  1895.  
  1896.     if (argc < 2)
  1897.     {
  1898.         printf("text2data for FamiTone2 NES audio library\n");
  1899.         printf("by Shiru (shiru@mail.ru), 04'17\n\n");
  1900.         printf("Usage: text2data.exe song.txt [-ca65 or -asm6][-ch1..5][-s][-allin]\n");
  1901.  
  1902.         return 0;
  1903.     }
  1904.  
  1905.     outtype = OUT_NESASM;
  1906.     strcpy(inname, "");
  1907.     channels = 5;    //process all channels
  1908.     separate = false; //export all subsongs as one file
  1909.  
  1910.     for (i = 1; i < argc; ++i)
  1911.     {
  1912.         if (!strcasecmp(argv[i], "-ca65"))
  1913.             outtype = OUT_CA65;
  1914.         if (!strcasecmp(argv[i], "-asm6"))
  1915.             outtype = OUT_ASM6;
  1916.         if (!strcasecmp(argv[i], "-ch5"))
  1917.             channels = 5;
  1918.         if (!strcasecmp(argv[i], "-ch4"))
  1919.             channels = 4;
  1920.         if (!strcasecmp(argv[i], "-ch3"))
  1921.             channels = 3;
  1922.         if (!strcasecmp(argv[i], "-ch2"))
  1923.             channels = 2;
  1924.         if (!strcasecmp(argv[i], "-ch1"))
  1925.             channels = 1;
  1926.         if (!strcasecmp(argv[i], "-s"))
  1927.             separate = true;
  1928.         if (!strcasecmp(argv[i], "-allin"))
  1929.             keep_instruments = 1;
  1930.  
  1931.         if (argv[i][0] != '-')
  1932.             strcpy(inname, argv[i]);
  1933.     }
  1934.  
  1935.     atexit(exit_proc);
  1936.  
  1937.     if (!text_open(inname))
  1938.     {
  1939.         printf("Can't open file '%s'\n", inname);
  1940.         return 1;
  1941.     }
  1942.  
  1943.     //generate output filenames and song name
  1944.  
  1945.     strcpy(outname, inname);
  1946.  
  1947.     for (i = strlen(outname) - 1; i >= 0; --i)
  1948.     {
  1949.         if (outname[i] == '.')
  1950.         {
  1951.             outname[i] = 0;
  1952.             break;
  1953.         }
  1954.     }
  1955.  
  1956.     strcpy(songName, outname);
  1957.     strcpy(dpcmname, outname);
  1958.     strcat(dpcmname, ".dmc");
  1959.  
  1960.     for (i = strlen(songName) - 1; i >= 0; --i)
  1961.     {
  1962.         c = songName[i];
  1963.  
  1964.         if (c == '\\' || c == '/')
  1965.         {
  1966.             strcpy(songName, &songName[i + 1]);
  1967.             break;
  1968.         }
  1969.  
  1970.         if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')))
  1971.             songName[i] = '_';
  1972.     }
  1973.  
  1974.     //process data
  1975.  
  1976.     printf("Output format: ");
  1977.  
  1978.     switch (outtype)
  1979.     {
  1980.     case OUT_NESASM:
  1981.         printf("NESASM");
  1982.         strcpy(DB, ".db");
  1983.         strcpy(DW, ".dw");
  1984.         strcpy(LL, ".");
  1985.         strcpy(LOW, "LOW");
  1986.         break;
  1987.  
  1988.     case OUT_CA65:
  1989.         printf("CA65");
  1990.         strcpy(DB, ".byte");
  1991.         strcpy(DW, ".word");
  1992.         strcpy(LL, "@");
  1993.         strcpy(LOW, ".lobyte");
  1994.         break;
  1995.  
  1996.     case OUT_ASM6:
  1997.         printf("Asm6");
  1998.         strcpy(DB, "db");
  1999.         strcpy(DW, "dw");
  2000.         strcpy(LL, "@");
  2001.         strcpy(LOW, "<");
  2002.         break;
  2003.     }
  2004.  
  2005.     printf(", ");
  2006.  
  2007.     if (!separate)
  2008.         printf("all songs in single file\n");
  2009.     else
  2010.         printf("each song in a separate file\n");
  2011.  
  2012.     if (text_find_tag("# FamiTracker text export", 0) >= 0)
  2013.     {
  2014.         printf("Input format: FamiTracker export\n");
  2015.  
  2016.         if (!separate)
  2017.         {
  2018.             clear_packed_patterns();
  2019.             clear_instruments();
  2020.             parse_instruments();
  2021.  
  2022.             for (sub = 0; sub < subSongsCount; ++sub) //mark all used instruments in all subsongs
  2023.             {
  2024.                 clear_song();
  2025.                 parse_song(sub, false);
  2026.                 song_cleanup_instrument_numbers();
  2027.             }
  2028.  
  2029.             envelopes_cleanup();
  2030.             envelope_pitch_convert();
  2031.  
  2032.             if (outtype != OUT_CA65)
  2033.                 strcat(outname, ".asm");
  2034.             else
  2035.                 strcat(outname, ".s");
  2036.  
  2037.             output_open(outname);
  2038.  
  2039.             size_header = output_header(songName, -1);
  2040.             size_instruments = output_instruments();
  2041.  
  2042.             clear_packed_patterns();
  2043.  
  2044.             for (sub = 0; sub < subSongsCount; ++sub)
  2045.             {
  2046.                 clear_song();
  2047.                 parse_song(sub, false);
  2048.                 song_cleanup_instrument_numbers();
  2049.  
  2050.                 size_song[sub] = process_and_output_song(sub);
  2051.             }
  2052.  
  2053.             output_close();
  2054.  
  2055.             size_total = size_header + size_instruments;
  2056.  
  2057.             printf("Header:     %i\n", size_header);
  2058.             printf("Instrument: %i\n", size_instruments);
  2059.  
  2060.             for (i = 0; i < subSongsCount; ++i)
  2061.             {
  2062.                 printf("Sub song %i: %i\n", i, size_song[i]);
  2063.                 size_total += size_song[i];
  2064.             }
  2065.  
  2066.             printf("\nTotal data size: %i bytes\n", size_total);
  2067.         }
  2068.         else
  2069.         {
  2070.             clear_packed_patterns();
  2071.             clear_instruments();
  2072.             parse_instruments();
  2073.             envelopes_cleanup();
  2074.             envelope_pitch_convert();
  2075.  
  2076.             for (sub = 0; sub < subSongsCount; ++sub)
  2077.             {
  2078.                 for (i = 0; i < MAX_INSTRUMENTS; ++i)
  2079.                     instruments[i].in_use = false;
  2080.  
  2081.                 clear_song();
  2082.                 parse_song(sub, false);
  2083.                 song_cleanup_instrument_numbers();
  2084.  
  2085.                 sprintf(outname1, "%s_%i", outname, sub);
  2086.  
  2087.                 if (outtype != OUT_CA65)
  2088.                     strcat(outname1, ".asm");
  2089.                 else
  2090.                     strcat(outname1, ".s");
  2091.  
  2092.                 output_open(outname1);
  2093.  
  2094.                 sprintf(songName1, "%s_%i", songName, sub);
  2095.  
  2096.                 size_header = output_header(songName1, sub);
  2097.                 size_instruments = output_instruments();
  2098.  
  2099.                 clear_packed_patterns();
  2100.  
  2101.                 size_song[sub] = process_and_output_song(sub);
  2102.  
  2103.                 output_close();
  2104.  
  2105.                 printf("Sub song %i: %i\n", sub, size_header + size_instruments + size_song[sub]);
  2106.             }
  2107.         }
  2108.     }
  2109.     else
  2110.     {
  2111.         // ** removed 'old'
  2112.         printf("\nGet Famitracker 0.4.6 or newer.\n");
  2113.         return 0;
  2114.     }
  2115.  
  2116.     text_close();
  2117.  
  2118.     if (dpcm_size) //save samples
  2119.     {
  2120.         file = fopen(dpcmname, "wb");
  2121.         fwrite(dpcm, dpcm_size, 1, file);
  2122.         fclose(file);
  2123.     }
  2124.  
  2125.     //song_text_dump(song_original);
  2126.  
  2127.     if (dpcm_size < 0)
  2128.     {
  2129.         printf("\nNo DPCM samples\n");
  2130.     }
  2131.     else
  2132.     {
  2133.         printf("\nDPCM samples: %i bytes\n", dpcm_size);
  2134.     }
  2135.  
  2136.     return 0;
  2137. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top