home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / goattracker_2.73.zip / src / gt2reloc.c < prev    next >
C/C++ Source or Header  |  2014-07-23  |  12KB  |  441 lines

  1. //
  2. // GOATTRACKER v2.73 - gt2reloc (commandline relocator/packer)
  3. //
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; either version 2 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program; if not, write to the Free Software
  16. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17. //
  18.  
  19. #define GOATTRK2_C
  20.  
  21. #ifdef __WIN32__
  22. #include <windows.h>
  23. #endif
  24.  
  25. #include "goattrk2.h"
  26. #include "bme.h"
  27.  
  28. int menu = 0;
  29. int editmode = EDIT_PATTERN;
  30. int recordmode = 1;
  31. int followplay = 0;
  32. int hexnybble = -1;
  33. int stepsize = 4;
  34. int autoadvance = 0;
  35. int defaultpatternlength = 64;
  36. int cursorflash = 0;
  37. int cursorcolortable[] = {1,2,7,2};
  38. int exitprogram = 0;
  39. int eacolumn = 0;
  40. int eamode = 0;
  41.  
  42. unsigned keypreset = KEY_TRACKER;
  43. unsigned playerversion = 0;
  44. int fileformat = FORMAT_PRG;
  45. int zeropageadr = 0xfc;
  46. int playeradr = 0x1000;
  47. unsigned sidmodel = 0;
  48. unsigned multiplier = 1;
  49. unsigned adparam = 0x0f00;
  50. unsigned ntsc = 0;
  51. unsigned patternhex = 0;
  52. unsigned sidaddress = 0xd400;
  53. unsigned finevibrato = 1;
  54. unsigned optimizepulse = 1;
  55. unsigned optimizerealtime = 1;
  56. unsigned customclockrate = 0;
  57. unsigned usefinevib = 0;
  58. unsigned b = DEFAULTBUF;
  59. unsigned mr = DEFAULTMIXRATE;
  60. unsigned writer = 0;
  61. unsigned hardsid = 0;
  62. unsigned catweasel = 0;
  63. unsigned interpolate = 0;
  64. unsigned residdelay = 0;
  65. unsigned hardsidbufinteractive = 20;
  66. unsigned hardsidbufplayback = 400;
  67. float basepitch = 0.0f;
  68.  
  69. char configbuf[MAX_PATHNAME];
  70. char loadedsongfilename[MAX_FILENAME];
  71. char songfilename[MAX_FILENAME];
  72. char songfilter[MAX_FILENAME];
  73. char songpath[MAX_PATHNAME];
  74. char instrfilename[MAX_FILENAME];
  75. char instrfilter[MAX_FILENAME];
  76. char instrpath[MAX_PATHNAME];
  77. char packedpath[MAX_PATHNAME];
  78. char packedsongname[MAX_PATHNAME];
  79.  
  80. char *programname = "$VER: GoatTracker v2.73";
  81.  
  82. char textbuffer[MAX_PATHNAME];
  83.  
  84. extern unsigned char datafile[];
  85.  
  86. #ifdef __WIN32__
  87. FILE *STDOUT, *STDERR;
  88. #else
  89. #define STDOUT stdout
  90. #define STDERR stderr
  91. #endif
  92.  
  93. void usage(void)
  94. {
  95.     fprintf(STDOUT, "Usage: GT2RELOC <songname> <outfile> [options]\n");
  96.     fprintf(STDOUT, "Options:\n");
  97.     fprintf(STDOUT, "-Axx Set ADSR parameter for hardrestart in hex. DEFAULT=0F00\n");
  98.     fprintf(STDOUT, "-Bx  enable/disable buffered SID writes. DEFAULT=disabled\n");
  99.     fprintf(STDOUT, "-Cx  enable/disable zeropage ghost registers. DEFAULT=disabled\n");
  100.     fprintf(STDOUT, "-Dx  enable/disable sound effect support. DEFAULT=disabled\n");
  101.     fprintf(STDOUT, "-Ex  enable/disable volume change support. DEFAULT=disabled\n");
  102.     fprintf(STDOUT, "-Fxx Set custom SID clock cycles per second (0 = use PAL/NTSC default)\n");
  103.     fprintf(STDOUT, "-Gxx Set pitch of A-4 in Hz (0 = use default frequencytable, close to 440Hz)\n");
  104.     fprintf(STDOUT, "-Hx  enable/disable storing of author info. DEFAULT=disabled\n");
  105.     fprintf(STDOUT, "-Ix  enable/disable optimizations. DEFAULT=enabled\n");
  106.     fprintf(STDOUT, "-Jx  enable/disable full buffering. DEFAULT=disabled\n");
  107.     fprintf(STDOUT, "-Lxx SID memory location in hex. DEFAULT=D400\n");
  108.     fprintf(STDOUT, "-N   Use NTSC timing\n");
  109.     fprintf(STDOUT, "-Oxx Set pulseoptimization/skipping (0 = off, 1 = on) DEFAULT=on\n");
  110.     fprintf(STDOUT, "-P   Use PAL timing (DEFAULT)\n");
  111.     fprintf(STDOUT, "-Rxx Set realtime-effect optimization/skipping (0 = off, 1 = on) DEFAULT=on\n");
  112.     fprintf(STDOUT, "-Sxx Set speed multiplier (0 for 25Hz, 1 for 1x, 2 for 2x etc.) DEFAULT=1\n");
  113.     fprintf(STDOUT, "-Vxx Set finevibrato conversion (0 = off, 1 = on) DEFAULT=on\n");
  114.     fprintf(STDOUT, "-Wxx player memory location highbyte in hex. DEFAULT=1000\n");
  115.     fprintf(STDOUT, "-Zxx zeropage memory location in hex. DEFAULT=FC\n");
  116.     fprintf(STDOUT, "-?   Show options\n");
  117. }
  118.  
  119. int main(int argc, char **argv)
  120. {
  121.   int c;
  122.  
  123. #ifdef __WIN32__
  124.   /*
  125.     SDL_Init() reroutes stdout and stderr, either to stdout.txt and stderr.txt
  126.     or to nirwana. simply reopening these handles does, other than suggested on
  127.     some web pages, not work reliably - opening new files on CON using different
  128.     handles however does.
  129.   */
  130.   STDOUT = fopen("CON", "w");
  131.   STDERR = fopen("CON", "w");
  132. #endif
  133.  
  134.   programname += sizeof "$VER:";
  135.   // Open datafile
  136.   io_openlinkeddatafile(datafile);
  137.  
  138.   // Reset channels/song
  139.   initchannels();
  140.   clearsong(1,1,1,1,1);
  141.  
  142.   // get input- and output file names
  143.   if (argc >= 3) {
  144.       strcpy(songfilename, argv[1]);
  145.       strcpy(packedsongname, argv[2]);
  146.   } else {
  147.       usage();
  148.       exit(-1);
  149.   }
  150.  
  151.   // Load song
  152.   if (strlen(songfilename)) {
  153.       loadsong();
  154.   } else {
  155.       fprintf(STDERR, "error: no song filename given.\n");
  156.       exit (-1);
  157.   }
  158.  
  159.   c = strlen(packedsongname);
  160.   if (strlen(packedsongname) <= 0) {
  161.       fprintf(STDERR, "error: no output filename given.\n");
  162.       exit (-1);
  163.   }
  164.  
  165.   // determine output format from file extension of the output filename
  166.   c--;
  167.   while ((c > 0) && (packedsongname[c] != '.')) c--;
  168.   if (packedsongname[c] == '.') c++;
  169.  
  170.   if (!strcmp(&packedsongname[c], "sid")) {
  171.       fileformat = FORMAT_SID;
  172.   } else if (!strcmp(&packedsongname[c], "prg")) {
  173.       fileformat = FORMAT_PRG;
  174.   } else if (!strcmp(&packedsongname[c], "bin")) {
  175.       fileformat = FORMAT_BIN;
  176.   } else {
  177.       fileformat = FORMAT_PRG;
  178.   }
  179.  
  180.   fprintf(STDOUT, "%s Packer/Relocator\n", programname);
  181.   fprintf(STDOUT, "song file:       %s\n", loadedsongfilename);
  182.   fprintf(STDOUT, "output file:     %s\n", packedsongname);
  183.   fprintf(STDOUT, "output format:   ");
  184.   if (fileformat == FORMAT_SID) {
  185.       fprintf(STDOUT, "sid\n");
  186.   } else if (fileformat == FORMAT_BIN) {
  187.       fprintf(STDOUT, "bin\n");
  188.   } else {
  189.       fprintf(STDOUT, "prg\n");
  190.   }
  191.  
  192.   // Scan command line
  193.   for (c = 3; c < argc; c++)
  194.   {
  195.     #ifdef __WIN32__
  196.     if ((argv[c][0] == '-') || (argv[c][0] == '/'))
  197.     #else
  198.     if (argv[c][0] == '-')
  199.     #endif
  200.     {
  201.       switch(toupper(argv[c][1]))
  202.       {
  203.         case '?':
  204.         return 0;
  205.  
  206.         case 'A':
  207.         sscanf(&argv[c][2], "%x", &adparam);
  208.         break;
  209.  
  210.         case 'G':
  211.         sscanf(&argv[c][2], "%f", &basepitch);
  212.         break;
  213.  
  214.         case 'L':
  215.         sscanf(&argv[c][2], "%x", &sidaddress);
  216.         break;
  217.  
  218.         case 'O':
  219.         sscanf(&argv[c][2], "%u", &optimizepulse);
  220.         break;
  221.  
  222.         case 'R':
  223.         sscanf(&argv[c][2], "%u", &optimizerealtime);
  224.         break;
  225.  
  226.         case 'V':
  227.         sscanf(&argv[c][2], "%u", &finevibrato);
  228.         break;
  229.  
  230.         case 'S':
  231.         sscanf(&argv[c][2], "%u", &multiplier);
  232.         break;
  233.  
  234.         // NTSC timing
  235.         case 'N':
  236.         ntsc = 1;
  237.         customclockrate = 0;
  238.         break;
  239.         // PAL timing
  240.         case 'P':
  241.         ntsc = 0;
  242.         customclockrate = 0;
  243.         break;
  244.         // custom clock rate
  245.         case 'F':
  246.         sscanf(&argv[c][2], "%u", &customclockrate);
  247.         break;
  248.  
  249.         // player options (first menu)
  250.         // 0: Buffered SID-writes
  251.         case 'B':
  252.             if (argv[c][2] == '1') {
  253.                 playerversion |= PLAYER_BUFFERED;
  254.             } else {
  255.                 playerversion &= ~PLAYER_BUFFERED;
  256.             }
  257.         break;
  258.         // 1: Sound effect support
  259.         case 'D':
  260.             if (argv[c][2] == '1') {
  261.                 playerversion |= PLAYER_SOUNDEFFECTS;
  262.             } else {
  263.                 playerversion &= ~PLAYER_SOUNDEFFECTS;
  264.             }
  265.         break;
  266.         // 2: Volume change support
  267.         case 'E':
  268.             if (argv[c][2] == '1') {
  269.                 playerversion |= PLAYER_VOLUME;
  270.             } else {
  271.                 playerversion &= ~PLAYER_VOLUME;
  272.             }
  273.         break;
  274.         // 3: Store author-info
  275.         case 'H':
  276.             if (argv[c][2] == '1') {
  277.                 playerversion |= PLAYER_AUTHORINFO;
  278.             } else {
  279.                 playerversion &= ~PLAYER_AUTHORINFO;
  280.             }
  281.         break;
  282.         // 4: Use zeropage ghostregs
  283.         case 'C':
  284.             if (argv[c][2] == '1') {
  285.                 playerversion |= PLAYER_ZPGHOSTREGS;
  286.             } else {
  287.                 playerversion &= ~PLAYER_ZPGHOSTREGS;
  288.             }
  289.         break;
  290.         // 5: Disable optimization
  291.         case 'I':
  292.             if (argv[c][2] == '1') {
  293.                 playerversion &= ~PLAYER_NOOPTIMIZATION;
  294.             } else {
  295.                 playerversion |= PLAYER_NOOPTIMIZATION;
  296.             }
  297.         // 6: Full buffering
  298.         case 'J':
  299.             if (argv[c][2] == '1') {
  300.                 playerversion &= ~PLAYER_FULLBUFFERED;
  301.             } else {
  302.                 playerversion |= PLAYER_FULLBUFFERED;
  303.             }
  304.         break;
  305.  
  306.         // start address (second menu)
  307.         case 'W':
  308.         sscanf(&argv[c][2], "%x", &playeradr);
  309.         playeradr<<=8;
  310.         break;
  311.  
  312.         // zeropage address (third menu)
  313.         case 'Z':
  314.         sscanf(&argv[c][2], "%x", &zeropageadr);
  315.         break;
  316.       }
  317.     }
  318.     else
  319.     {
  320.       fprintf(STDERR, "error: unknown option\n");
  321.       usage();
  322.       exit(-1);
  323.     }
  324.   }
  325.  
  326.   // Validate parameters
  327.   sidmodel &= 1;
  328.   adparam &= 0xffff;
  329.   zeropageadr &= 0xff;
  330.   playeradr &= 0xff00;
  331.   sidaddress &= 0xffff;
  332.  
  333.   if (multiplier > 16) multiplier = 16;
  334.   if ((finevibrato == 1) && (multiplier < 2)) usefinevib = 1;
  335.   if (finevibrato > 1) usefinevib = 1;
  336.   if (optimizepulse > 1) optimizepulse = 1;
  337.   if (optimizerealtime > 1) optimizerealtime = 1;
  338.   if (customclockrate < 100) customclockrate = 0;
  339.  
  340.   // Calculate frequencytable if necessary
  341.   if (basepitch < 0.0f)
  342.     basepitch = 0.0f;
  343.   if (basepitch > 0.0f)
  344.     calculatefreqtable();
  345.  
  346.   // perform relocation
  347.   relocator();
  348.  
  349.   // Exit
  350.   return 0;
  351. }
  352.  
  353. void waitkeymousenoupdate(void)
  354. {
  355. }
  356.  
  357. void getparam(FILE *handle, unsigned *value)
  358. {
  359.   char *configptr;
  360.  
  361.   for (;;)
  362.   {
  363.     if (feof(handle)) return;
  364.     fgets(configbuf, MAX_PATHNAME, handle);
  365.     if ((configbuf[0]) && (configbuf[0] != ';') && (configbuf[0] != ' ') && (configbuf[0] != 13) && (configbuf[0] != 10)) break;
  366.   }
  367.  
  368.   configptr = configbuf;
  369.   if (*configptr == '$')
  370.   {
  371.     *value = 0;
  372.     configptr++;
  373.     for (;;)
  374.     {
  375.       char c = tolower(*configptr++);
  376.       int h = -1;
  377.  
  378.       if ((c >= 'a') && (c <= 'f')) h = c - 'a' + 10;
  379.       if ((c >= '0') && (c <= '9')) h = c - '0';
  380.  
  381.       if (h >= 0)
  382.       {
  383.         *value *= 16;
  384.         *value += h;
  385.       }
  386.       else break;
  387.     }
  388.   }
  389.   else
  390.   {
  391.     *value = 0;
  392.     for (;;)
  393.     {
  394.       char c = tolower(*configptr++);
  395.       int d = -1;
  396.  
  397.       if ((c >= '0') && (c <= '9')) d = c - '0';
  398.  
  399.       if (d >= 0)
  400.       {
  401.         *value *= 10;
  402.         *value += d;
  403.       }
  404.       else break;
  405.     }
  406.   }
  407. }
  408.  
  409. void getfloatparam(FILE *handle, float *value)
  410. {
  411.   char *configptr;
  412.  
  413.   for (;;)
  414.   {
  415.     if (feof(handle)) return;
  416.     fgets(configbuf, MAX_PATHNAME, handle);
  417.     if ((configbuf[0]) && (configbuf[0] != ';') && (configbuf[0] != ' ') && (configbuf[0] != 13) && (configbuf[0] != 10)) break;
  418.   }
  419.  
  420.   configptr = configbuf;
  421.   *value = 0.0f;
  422.   sscanf(configptr, "%f", value);
  423. }
  424.  
  425. void calculatefreqtable()
  426. {
  427.   double basefreq = (double)basepitch * (16777216.0 / 985248.0) * pow(2.0, 0.25) / 32.0;
  428.   int c;
  429.  
  430.   for (c = 0; c < 8*12 ; c++)
  431.   {
  432.     double note = c;
  433.     double freq = basefreq * pow(2.0, note/12.0);
  434.     int intfreq = freq + 0.5;
  435.     if (intfreq > 0xffff)
  436.         intfreq = 0xffff;
  437.     freqtbllo[c] = intfreq & 0xff;
  438.     freqtblhi[c] = intfreq >> 8;
  439.   }
  440. }
  441.