Advertisement
Guest User

Famitone 3.2 Unofficial - Cross Platform

a guest
Mar 3rd, 2018
569
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 41.60 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement