home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / goattracker_2.71_stereo.zip / src / gt2stereo.c < prev    next >
C/C++ Source or Header  |  2010-10-21  |  36KB  |  1,402 lines

  1. //
  2. // GOATTRACKER v2.71 Stereo
  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 = 0xd500d400;
  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.  
  79. char *programname = "GoatTracker v2.71 Stereo";
  80.  
  81. char textbuffer[MAX_PATHNAME];
  82.  
  83. unsigned char hexkeytbl[] = {'0', '1', '2', '3', '4', '5', '6', '7',
  84.   '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
  85.  
  86. extern unsigned char datafile[];
  87.  
  88. int main(int argc, char **argv)
  89. {
  90.   char filename[MAX_PATHNAME];
  91.   FILE *configfile;
  92.   int c,d;
  93.  
  94.   // Open datafile
  95.   io_openlinkeddatafile(datafile);
  96.  
  97.   // Load configuration
  98.   #ifdef __WIN32__
  99.   GetModuleFileName(NULL, filename, MAX_PATHNAME);
  100.   filename[strlen(filename)-3] = 'c';
  101.   filename[strlen(filename)-2] = 'f';
  102.   filename[strlen(filename)-1] = 'g';
  103.   #elif __amigaos__
  104.   strcpy(filename, "PROGDIR:goattrk2.cfg");
  105.   #else
  106.   strcpy(filename, getenv("HOME"));
  107.   strcat(filename, "/.goattrk/gt2stereo.cfg");
  108.   #endif
  109.   configfile = fopen(filename, "rt");
  110.   if (configfile)
  111.   {
  112.     getparam(configfile, &b);
  113.     getparam(configfile, &mr);
  114.     getparam(configfile, &hardsid);
  115.     getparam(configfile, &sidmodel);
  116.     getparam(configfile, &ntsc);
  117.     getparam(configfile, (unsigned *)&fileformat);
  118.     getparam(configfile, (unsigned *)&playeradr);
  119.     getparam(configfile, (unsigned *)&zeropageadr);
  120.     getparam(configfile, &playerversion);
  121.     getparam(configfile, &keypreset);
  122.     getparam(configfile, (unsigned *)&stepsize);
  123.     getparam(configfile, &multiplier);
  124.     getparam(configfile, &catweasel);
  125.     getparam(configfile, &adparam);
  126.     getparam(configfile, &interpolate);
  127.     getparam(configfile, &patternhex);
  128.     getparam(configfile, &sidaddress);
  129.     getparam(configfile, &finevibrato);
  130.     getparam(configfile, &optimizepulse);
  131.     getparam(configfile, &optimizerealtime);
  132.     getparam(configfile, &residdelay);
  133.     getparam(configfile, &customclockrate);
  134.     getparam(configfile, &hardsidbufinteractive);
  135.     getparam(configfile, &hardsidbufplayback);
  136.     getfloatparam(configfile, &filterparams.distortionrate);
  137.     getfloatparam(configfile, &filterparams.distortionpoint);
  138.     getfloatparam(configfile, &filterparams.distortioncfthreshold);
  139.     getfloatparam(configfile, &filterparams.type3baseresistance);
  140.     getfloatparam(configfile, &filterparams.type3offset);
  141.     getfloatparam(configfile, &filterparams.type3steepness);
  142.     getfloatparam(configfile, &filterparams.type3minimumfetresistance);
  143.     getfloatparam(configfile, &filterparams.type4k);
  144.     getfloatparam(configfile, &filterparams.type4b);
  145.     getfloatparam(configfile, &filterparams.voicenonlinearity);
  146.     getparam(configfile, &win_fullscreen);
  147.     getfloatparam(configfile, &basepitch);
  148.     fclose(configfile);
  149.   }
  150.  
  151.   // Init pathnames
  152.   initpaths();
  153.  
  154.   // Scan command line
  155.   for (c = 1; c < argc; c++)
  156.   {
  157.     #ifdef __WIN32__
  158.     if ((argv[c][0] == '-') || (argv[c][0] == '/'))
  159.     #else
  160.     if (argv[c][0] == '-')
  161.     #endif
  162.     {
  163.       int y = 0;
  164.       switch(toupper(argv[c][1]))
  165.       {
  166.         case '?':
  167.         if (!initscreen())
  168.           return 1;       
  169.         if (argv[c][2]=='?') {
  170.           onlinehelp(1,0);
  171.           return 0;
  172.         }
  173.  
  174.         printtext(0,y++,15,"Usage: GT2STEREO [songname] [options]");
  175.         printtext(0,y++,15,"Options:");
  176.         printtext(0,y++,15,"-Axx Set ADSR parameter for hardrestart in hex. DEFAULT=0F00");
  177.         printtext(0,y++,15,"-Bxx Set sound buffer length in milliseconds DEFAULT=100");
  178.         printtext(0,y++,15,"-Cxx Use CatWeasel MK3 PCI SID (0 = off, 1 = on)");
  179.         printtext(0,y++,15,"-Dxx Pattern row display (0 = decimal, 1 = hexadecimal)");
  180.         printtext(0,y++,15,"-Exx Set emulated SID model (0 = 6581 1 = 8580) DEFAULT=6581");
  181.         printtext(0,y++,15,"-Fxx Set custom SID clock cycles per second (0 = use PAL/NTSC default)");
  182.         printtext(0,y++,15,"-Gxx Set pitch of A-4 in Hz (0 = use default frequencytable, close to 440Hz)");
  183.         printtext(0,y++,15,"-Hxx Use HardSID (0 = off, 1 = HardSID ID0 2 = HardSID ID1 etc.)");
  184.         printtext(0,y++,15,"     Use high nybble (it's hexadecimal) to specify right HardSID ID");
  185.         printtext(0,y++,15,"-Ixx Set reSID interpolation (0 = off, 1 = on, 2 = distortion, 3 = distortion & on) DEFAULT=off");
  186.         printtext(0,y++,15,"-Kxx Note-entry mode (0 = PROTRACKER 1 = DMC) DEFAULT=PROTRK.");
  187.         printtext(0,y++,15,"-Lxx SID memory locations in hex. DEFAULT=D500D400");
  188.         printtext(0,y++,15,"-Mxx Set sound mixing rate DEFAULT=44100");
  189.         printtext(0,y++,15,"-Oxx Set pulseoptimization/skipping (0 = off, 1 = on) DEFAULT=on");
  190.         printtext(0,y++,15,"-Rxx Set realtime-effect optimization/skipping (0 = off, 1 = on) DEFAULT=on");
  191.         printtext(0,y++,15,"-Sxx Set speed multiplier (0 for 25Hz, 1 for 1x, 2 for 2x etc.)");
  192.         printtext(0,y++,15,"-Txx Set HardSID interactive mode sound buffer length in milliseconds DEFAULT=20, max.buffering=0");
  193.         printtext(0,y++,15,"-Uxx Set HardSID playback mode sound buffer length in milliseconds DEFAULT=400, max.buffering=0");
  194.         printtext(0,y++,15,"-Vxx Set finevibrato conversion (0 = off, 1 = on) DEFAULT=on");
  195.         printtext(0,y++,15,"-Xxx Set window type (0 = window, 1 = fullscreen) DEFAULT=window");
  196.         printtext(0,y++,15,"-Zxx Set random reSID write delay in cycles (0 = off) DEFAULT=off");
  197.         printtext(0,y++,15,"-N   Use NTSC timing");
  198.         printtext(0,y++,15,"-P   Use PAL timing (DEFAULT)");
  199.         printtext(0,y++,15,"-W   Write sound output to a file SIDAUDIO.RAW");
  200.         printtext(0,y++,15,"-?   Show this info again");
  201.         printtext(0,y++,15,"-??  Standalone online help window");
  202.         waitkeynoupdate();
  203.         return 0;
  204.  
  205.         case 'Z':
  206.         sscanf(&argv[c][2], "%u", &residdelay);
  207.         break;
  208.  
  209.         case 'A':
  210.         sscanf(&argv[c][2], "%x", &adparam);
  211.         break;
  212.  
  213.         case 'S':
  214.         sscanf(&argv[c][2], "%u", &multiplier);
  215.         break;
  216.  
  217.         case 'B':
  218.         sscanf(&argv[c][2], "%u", &b);
  219.         break;
  220.  
  221.         case 'D':
  222.         sscanf(&argv[c][2], "%u", &patternhex);
  223.         break;
  224.  
  225.         case 'E':
  226.         sscanf(&argv[c][2], "%u", &sidmodel);
  227.         break;
  228.  
  229.         case 'I':
  230.         sscanf(&argv[c][2], "%u", &interpolate);
  231.         break;
  232.  
  233.         case 'K':
  234.         sscanf(&argv[c][2], "%u", &keypreset);
  235.         break;
  236.  
  237.         case 'L':
  238.         sscanf(&argv[c][2], "%x", &sidaddress);
  239.         break;
  240.  
  241.         case 'N':
  242.         ntsc = 1;
  243.         customclockrate = 0;
  244.         break;
  245.  
  246.         case 'P':
  247.         ntsc = 0;
  248.         customclockrate = 0;
  249.         break;
  250.  
  251.         case 'F':
  252.         sscanf(&argv[c][2], "%u", &customclockrate);
  253.         break;
  254.  
  255.         case 'M':
  256.         sscanf(&argv[c][2], "%u", &mr);
  257.         break;
  258.  
  259.         case 'O':
  260.         sscanf(&argv[c][2], "%u", &optimizepulse);
  261.         break;
  262.  
  263.         case 'R':
  264.         sscanf(&argv[c][2], "%u", &optimizerealtime);
  265.         break;
  266.  
  267.         case 'H':
  268.         sscanf(&argv[c][2], "%x", &hardsid);
  269.         break;
  270.  
  271.         case 'V':
  272.         sscanf(&argv[c][2], "%u", &finevibrato);
  273.         break;
  274.  
  275.         case 'T':
  276.         sscanf(&argv[c][2], "%u", &hardsidbufinteractive);
  277.         break;
  278.  
  279.         case 'U':
  280.         sscanf(&argv[c][2], "%u", &hardsidbufplayback);
  281.         break;
  282.  
  283.         case 'W':
  284.         writer = 1;
  285.         break;
  286.  
  287.         case 'X':
  288.         sscanf(&argv[c][2], "%u", &win_fullscreen);
  289.         break;
  290.  
  291.         case 'C':
  292.         sscanf(&argv[c][2], "%u", &catweasel);
  293.         break;
  294.  
  295.         case 'G':
  296.         sscanf(&argv[c][2], "%f", &basepitch);
  297.         break;
  298.       }
  299.     }
  300.     else
  301.     {
  302.       char startpath[MAX_PATHNAME];
  303.  
  304.       strcpy(songfilename, argv[c]);
  305.       for (d = strlen(argv[c])-1; d >= 0; d--)
  306.       {
  307.         if ((argv[c][d] == '/') || (argv[c][d] == '\\'))
  308.         {
  309.           strcpy(startpath, argv[c]);
  310.           startpath[d+1] = 0;
  311.           chdir(startpath);
  312.           initpaths();
  313.           strcpy(songfilename, &argv[c][d+1]);
  314.           break;
  315.         }
  316.       }
  317.     }
  318.   }
  319.  
  320.   // Validate parameters
  321.   sidmodel &= 1;
  322.   adparam &= 0xffff;
  323.   zeropageadr &= 0xff;
  324.   playeradr &= 0xff00;
  325.   if (!stepsize) stepsize = 4;
  326.   if (multiplier > 16) multiplier = 16;
  327.   if (keypreset > 2) keypreset = 0;
  328.   if ((finevibrato == 1) && (multiplier < 2)) usefinevib = 1;
  329.   if (finevibrato > 1) usefinevib = 1;
  330.   if (optimizepulse > 1) optimizepulse = 1;
  331.   if (optimizerealtime > 1) optimizerealtime = 1;
  332.   if (residdelay > 63) residdelay = 63;
  333.   if (customclockrate < 100) customclockrate = 0;
  334.  
  335.   // Calculate frequencytable if necessary
  336.   if (basepitch < 0.0f)
  337.     basepitch = 0.0f;
  338.   if (basepitch > 0.0f)
  339.     calculatefreqtable();
  340.  
  341.   // Set screenmode
  342.   if (!initscreen())
  343.     return 1;
  344.  
  345.   // Reset channels/song
  346.   initchannels();
  347.   clearsong(1,1,1,1,1);
  348.  
  349.   // Init sound
  350.   if (!sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate))
  351.   {
  352.     printtextc(MAX_ROWS/2-1,15,"Sound init failed. Press any key to run without sound (notice that song timer won't start)");
  353.     waitkeynoupdate();
  354.   }
  355.  
  356.   // Load song if applicable
  357.   if (strlen(songfilename)) loadsong();
  358.  
  359.   // Start editor mainloop
  360.   printmainscreen();
  361.   while (!exitprogram)
  362.   {
  363.     waitkeymouse();
  364.     docommand();
  365.   }
  366.  
  367.   // Shutdown sound output now
  368.   sound_uninit();
  369.  
  370.   // Save configuration
  371.   #ifndef __WIN32__
  372.   #ifdef __amigaos__
  373.   strcpy(filename, "PROGDIR:goattrk2.cfg");
  374.   #else
  375.   strcpy(filename, getenv("HOME"));
  376.   strcat(filename, "/.goattrk");
  377.   mkdir(filename, S_IRUSR | S_IWUSR | S_IXUSR);
  378.   strcat(filename, "/gt2stereo.cfg");
  379.   #endif
  380.   #endif
  381.   configfile = fopen(filename, "wt");
  382.   if (configfile)
  383.   {
  384.     fprintf(configfile, ";------------------------------------------------------------------------------\n"
  385.                         ";GT2 config file. Rows starting with ; are comments. Hexadecimal parameters are\n"
  386.                         ";to be preceded with $ and decimal parameters with nothing.                    \n"
  387.                         ";------------------------------------------------------------------------------\n"
  388.                         "\n"
  389.                         ";reSID buffer length (in milliseconds)\n%d\n\n"
  390.                         ";reSID mixing rate (in Hz)\n%d\n\n"
  391.                         ";Hardsid device number (0 = off)\n%d\n\n"
  392.                         ";reSID model (0 = 6581, 1 = 8580)\n%d\n\n"
  393.                         ";Timing mode (0 = PAL, 1 = NTSC)\n%d\n\n"
  394.                         ";Packer/relocator fileformat (0 = SID, 1 = PRG, 2 = BIN)\n%d\n\n"
  395.                         ";Packer/relocator player address\n$%04x\n\n"
  396.                         ";Packer/relocator zeropage baseaddress\n$%02x\n\n"
  397.                         ";Packer/relocator player type (0 = standard ... 3 = minimal)\n%d\n\n"
  398.                         ";Key entry mode (0 = Protracker, 1 = DMC)\n%d\n\n"
  399.                         ";Pattern highlight step size\n%d\n\n"
  400.                         ";Speed multiplier (0 = 25Hz, 1 = 1X, 2 = 2X etc.)\n%d\n\n"
  401.                         ";Use CatWeasel SID (0 = off, 1 = on)\n%d\n\n"
  402.                         ";Hardrestart ADSR parameter\n$%04x\n\n"
  403.                         ";reSID interpolation (0 = off, 1 = on, 2 = distortion, 3 = distortion & on)\n%d\n\n"
  404.                         ";Hexadecimal pattern display (0 = off, 1 = on)\n%d\n\n"
  405.                         ";SID baseaddresses\n$%08x\n\n"
  406.                         ";Finevibrato mode (0 = off, 1 = on)\n%d\n\n"
  407.                         ";Pulseskipping (0 = off, 1 = on)\n%d\n\n"
  408.                         ";Realtime effect skipping (0 = off, 1 = on)\n%d\n\n"
  409.                         ";Random reSID write delay in cycles (0 = off)\n%d\n\n"
  410.                         ";Custom SID clock cycles per second (0 = use PAL/NTSC default)\n%d\n\n"
  411.                         ";HardSID interactive mode buffer size (in milliseconds, 0 = maximum/no flush)\n%d\n\n"
  412.                         ";HardSID playback mode buffer size (in milliseconds, 0 = maximum/no flush)\n%d\n\n"
  413.                         ";reSID-fp distortion rate\n%f\n\n"
  414.                         ";reSID-fp distortion point\n%f\n\n"
  415.                         ";reSID-fp distortion CF threshold\n%f\n\n"
  416.                         ";reSID-fp type 3 base resistance\n%f\n\n"
  417.                         ";reSID-fp type 3 base offset\n%f\n\n"
  418.                         ";reSID-fp type 3 base steepness\n%f\n\n"
  419.                         ";reSID-fp type 3 minimum FET resistance\n%f\n\n"
  420.                         ";reSID-fp type 4 k\n%f\n\n"
  421.                         ";reSID-fp type 4 b\n%f\n\n"
  422.                         ";reSID-fp voice nonlinearity\n%f\n\n"
  423.                         ";Window type (0 = window, 1 = fullscreen)\n%d\n\n"
  424.                         ";Base pitch of A-4 in Hz (0 = use default frequencytable)\n%f\n\n",
  425.     b,
  426.     mr,
  427.     hardsid,
  428.     sidmodel,
  429.     ntsc,
  430.     fileformat,
  431.     playeradr,
  432.     zeropageadr,
  433.     playerversion,
  434.     keypreset,
  435.     stepsize,
  436.     multiplier,
  437.     catweasel,
  438.     adparam,
  439.     interpolate,
  440.     patternhex,
  441.     sidaddress,
  442.     finevibrato,
  443.     optimizepulse,
  444.     optimizerealtime,
  445.     residdelay,
  446.     customclockrate,
  447.     hardsidbufinteractive,
  448.     hardsidbufplayback,
  449.     filterparams.distortionrate,
  450.     filterparams.distortionpoint,
  451.     filterparams.distortioncfthreshold,
  452.     filterparams.type3baseresistance,
  453.     filterparams.type3offset,
  454.     filterparams.type3steepness,
  455.     filterparams.type3minimumfetresistance,
  456.     filterparams.type4k,
  457.     filterparams.type4b,
  458.     filterparams.voicenonlinearity,
  459.     win_fullscreen,
  460.     basepitch);
  461.     fclose(configfile);
  462.   }
  463.  
  464.   // Exit
  465.   return 0;
  466. }
  467.  
  468. void waitkey(void)
  469. {
  470.   for (;;)
  471.   {
  472.     displayupdate();
  473.     getkey();
  474.     if ((rawkey) || (key)) break;
  475.     if (win_quitted) break;
  476.   }
  477.  
  478.   converthex();
  479. }
  480.  
  481. void waitkeymouse(void)
  482. {
  483.   for (;;)
  484.   {
  485.     displayupdate();
  486.     getkey();
  487.     if ((rawkey) || (key)) break;
  488.     if (win_quitted) break;
  489.     if (mouseb) break;
  490.   }
  491.  
  492.   converthex();
  493. }
  494.  
  495. void waitkeymousenoupdate(void)
  496. {
  497.   for (;;)
  498.   {
  499.       fliptoscreen();
  500.     getkey();
  501.     if ((rawkey) || (key)) break;
  502.     if (win_quitted) break;
  503.     if (mouseb) break;
  504.   }
  505.  
  506.   converthex();
  507. }
  508.  
  509. void waitkeynoupdate(void)
  510. {
  511.   for (;;)
  512.   {
  513.       fliptoscreen();
  514.     getkey();
  515.     if ((rawkey) || (key)) break;
  516.     if ((mouseb) && (!prevmouseb)) break;
  517.     if (win_quitted) break;
  518.   }
  519. }
  520.  
  521. void converthex()
  522. {
  523.   int c;
  524.  
  525.   hexnybble = -1;
  526.   for (c = 0; c < 16; c++)
  527.   {
  528.     if (tolower(key) == hexkeytbl[c])
  529.     {
  530.       if (c >= 10)
  531.       {
  532.         if (!shiftpressed) hexnybble = c;
  533.       }
  534.       else
  535.       {
  536.         hexnybble = c;
  537.       }
  538.     }
  539.   }
  540. }
  541.  
  542.  
  543. void docommand(void)
  544. {
  545.   // "GUI" operation :)
  546.   mousecommands();
  547.  
  548.   // Mode-specific commands
  549.   switch(editmode)
  550.   {
  551.     case EDIT_ORDERLIST:
  552.     orderlistcommands();
  553.     break;
  554.  
  555.     case EDIT_INSTRUMENT:
  556.     instrumentcommands();
  557.     break;
  558.  
  559.     case EDIT_TABLES:
  560.     tablecommands();
  561.     break;
  562.  
  563.     case EDIT_PATTERN:
  564.     patterncommands();
  565.     break;
  566.  
  567.     case EDIT_NAMES:
  568.     namecommands();
  569.     break;
  570.   }
  571.  
  572.   // General commands
  573.   generalcommands();
  574. }
  575.  
  576. void mousecommands(void)
  577. {
  578.   int c;
  579.  
  580.   if (!mouseb) return;
  581.  
  582.   // Pattern editpos & pattern number selection
  583.   for (c = 0; c < MAX_CHN; c++)
  584.   {
  585.     if ((mousey == 2) && (mousex >= 11 + c*9) && (mousex <= 12 + c*9))
  586.     {
  587.         if ((!prevmouseb) || (mouseheld > HOLDDELAY))
  588.         {
  589.         if (mouseb & MOUSEB_LEFT)
  590.         {
  591.           epchn = c;
  592.           nextpattern();
  593.         }
  594.         if (mouseb & MOUSEB_RIGHT)
  595.         {
  596.           epchn = c;
  597.           prevpattern();
  598.         }
  599.       }
  600.     }
  601.     else
  602.     {
  603.       if ((mousey >= 2) && (mousey <= 34) && (mousex >= 5 + c*9) && (mousex <= 12 + c*9))
  604.       {
  605.         int x = mousex - 5 - c*9;
  606.         int newpos = mousey - 3 + epview;
  607.         if (newpos < 0) newpos = 0;
  608.         if (newpos > pattlen[epnum[epchn]]) newpos = pattlen[epnum[epchn]];
  609.  
  610.         editmode = EDIT_PATTERN;
  611.  
  612.         if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (!prevmouseb))
  613.         {
  614.           if ((epmarkchn != c) || (newpos != epmarkend))
  615.           {
  616.             epmarkchn = c;
  617.             epmarkstart = epmarkend = newpos;
  618.           }
  619.         }
  620.  
  621.         if (mouseb & MOUSEB_LEFT)
  622.         {
  623.           epchn = c;
  624.           if (x < 3) epcolumn = 0;
  625.           if (x >= 3) epcolumn = x - 2;
  626.         }
  627.  
  628.         if (!prevmouseb)
  629.         {
  630.           if (mouseb & MOUSEB_LEFT)
  631.             eppos = newpos;
  632.         }
  633.         else
  634.         {
  635.             if (mouseb & MOUSEB_LEFT)
  636.             {
  637.             if (mousey == 2) eppos--;
  638.             if (mousey == 34) eppos++;
  639.           }
  640.         }
  641.         if (eppos < 0) eppos = 0;
  642.         if (eppos > pattlen[epnum[epchn]]) eppos = pattlen[epnum[epchn]];
  643.  
  644.         if (mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) epmarkend = newpos;
  645.       }
  646.     }
  647.   }
  648.  
  649.  
  650.   // Song editpos & songnumber selection
  651.   if ((mousey >= 3) && (mousey <= 8) && (mousex >= 40+20))
  652.   {
  653.     int newpos = esview + (mousex - 44 - 20) / 3;
  654.     int newcolumn = (mousex - 44 - 20) % 3;
  655.     int newchn = mousey - 3;
  656.     if (newcolumn < 0) newcolumn = 0;
  657.     if (newcolumn > 1) newcolumn = 1;
  658.     if (newpos < 0)
  659.     {
  660.       newpos = 0;
  661.       newcolumn = 0;
  662.     }
  663.     if (newpos == songlen[esnum][eschn])
  664.     {
  665.       newpos++;
  666.       newcolumn = 0;
  667.     }
  668.     if (newpos > songlen[esnum][eschn]+1)
  669.     {
  670.       newpos = songlen[esnum][eschn] + 1;
  671.       newcolumn = 1;
  672.     }
  673.  
  674.     editmode = EDIT_ORDERLIST;
  675.  
  676.     if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (!prevmouseb) && (newpos < songlen[esnum][eschn]))
  677.     {
  678.       if ((esmarkchn != newchn) || (newpos != esmarkend))
  679.       {
  680.         esmarkchn = newchn;
  681.         esmarkstart = esmarkend = newpos;
  682.       }
  683.     }
  684.  
  685.     if (mouseb & MOUSEB_LEFT)
  686.     {
  687.       eschn = newchn;
  688.       eseditpos = newpos;
  689.       escolumn = newcolumn;
  690.     }
  691.  
  692.     if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (newpos < songlen[esnum][eschn])) esmarkend = newpos;
  693.   }
  694.   if (((!prevmouseb) || (mouseheld > HOLDDELAY)) && (mousey == 2) && (mousex >= 63+20) && (mousex <= 64+20))
  695.   {
  696.     if (mouseb & MOUSEB_LEFT) nextsong();
  697.     if (mouseb & MOUSEB_RIGHT) prevsong();
  698.   }
  699.  
  700.   // Instrument editpos & instrument number selection
  701.   if ((mousey >= 8+3) && (mousey <= 12+3) && (mousex >= 56+20) && (mousex <= 57+20))
  702.   {
  703.     editmode = EDIT_INSTRUMENT;
  704.     eipos = mousey - 8 - 3;
  705.     eicolumn = mousex - 56 - 20;
  706.   }
  707.   if ((mousey >= 8+3) && (mousey <= 11+3) && (mousex >= 76+20) && (mousex <= 77+20))
  708.   {
  709.     editmode = EDIT_INSTRUMENT;
  710.     eipos = mousey - 8 - 3 + 5;
  711.     eicolumn = mousex - 76 - 20;
  712.   }
  713.   if ((mousey == 7+3) && (mousex >= 60+20))
  714.   {
  715.     editmode = EDIT_INSTRUMENT;
  716.     eipos = 9;
  717.   }
  718.   if (((!prevmouseb) || (mouseheld > HOLDDELAY)) && (mousey == 7+3) && (mousex >= 56+20) && (mousex <= 57+20))
  719.   {
  720.     if (mouseb & MOUSEB_LEFT) nextinstr();
  721.     if (mouseb & MOUSEB_RIGHT) previnstr();
  722.   }
  723.  
  724.   // Table editpos
  725.   for (c = 0; c < MAX_TABLES; c++)
  726.   {
  727.     if ((mousey >= 14+3) && (mousey <= 20+3+9) && (mousex >= 43 + 20 + c*10) && (mousex <= 47 + 20 + c*10))
  728.     {
  729.       int newpos = mousey - 15 - 3 + etview[etnum];
  730.       if (newpos < 0) newpos = 0;
  731.       if (newpos >= MAX_TABLELEN) newpos = MAX_TABLELEN-1;
  732.  
  733.       editmode = EDIT_TABLES;
  734.  
  735.       if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (!prevmouseb))
  736.       {
  737.         if ((etmarknum != etnum) || (newpos != etmarkend))
  738.         {
  739.           etmarknum = c;
  740.           etmarkstart = etmarkend = newpos;
  741.         }
  742.       }
  743.       if (mouseb & MOUSEB_LEFT)
  744.       {
  745.         etnum = c;
  746.         etpos = mousey - 15 - 3 + etview[etnum];
  747.         etcolumn = mousex - 43 - 20 - c*10;
  748.       }
  749.       if (etcolumn >= 2) etcolumn--;
  750.       if (etpos < 0) etpos = 0;
  751.       if (etpos > MAX_TABLELEN-1) etpos = MAX_TABLELEN-1;
  752.  
  753.       if (mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) etmarkend = newpos;
  754.     }
  755.   }
  756.  
  757.   // Name editpos
  758.   if ((mousey == 21+3+9) && (mousex >= 47+20))
  759.   {
  760.     editmode = EDIT_NAMES;
  761.     if ((!prevmouseb) && (mouseb & MOUSEB_RIGHT))
  762.     {
  763.       enpos++;
  764.       if (enpos > 2) enpos = 0;
  765.     }
  766.   }
  767.  
  768.   // Status panel
  769.   if ((!prevmouseb) && (mousex == 7) && (mousey == 23+3+9))
  770.   {
  771.     if (mouseb & (MOUSEB_LEFT))
  772.       if (epoctave < 7) epoctave++;
  773.     if (mouseb & (MOUSEB_RIGHT))
  774.       if (epoctave > 0) epoctave--;
  775.   }
  776.   if ((!prevmouseb) && (mousex <= 7) && (mousey == 24+3+9))
  777.   {
  778.     recordmode ^= 1;
  779.   }
  780.   for (c = 0; c < MAX_CHN; c++)
  781.   {
  782.     if ((!prevmouseb) && (mousey >= 23+3+9) && (mousex >= 59 + 7*c) && (mousex <= 64 + 7*c))
  783.       mutechannel(c);
  784.   }
  785.  
  786.   // Titlebar actions
  787.   if (!menu)
  788.   {
  789.     if ((mousey == 0) && (!prevmouseb) && (mouseb == MOUSEB_LEFT))
  790.     {
  791.       if ((mousex >= 40+20) && (mousex <= 41+20))
  792.       {
  793.         usefinevib ^= 1;
  794.       }
  795.       if ((mousex >= 43+20) && (mousex <= 44+20))
  796.       {
  797.         optimizepulse ^= 1;
  798.       }
  799.       if ((mousex >= 46+20) && (mousex <= 47+20))
  800.       {
  801.         optimizerealtime ^= 1;
  802.       }
  803.       if ((mousex >= 49+20) && (mousex <= 52+20))
  804.       {
  805.         ntsc ^= 1;
  806.         sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate);
  807.       }
  808.       if ((mousex >= 54+20) && (mousex <= 57+20))
  809.       {
  810.         sidmodel ^= 1;
  811.         sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate);
  812.       }
  813.       if ((mousex >= 62+20) && (mousex <= 65+20)) editadsr();
  814.       if ((mousex >= 67+20) && (mousex <= 68+20)) prevmultiplier();
  815.       if ((mousex >= 69+20) && (mousex <= 70+20)) nextmultiplier();
  816.     }
  817.   }
  818.   else
  819.   {
  820.     if ((!mousey) && (mouseb & MOUSEB_LEFT) && (!(prevmouseb & MOUSEB_LEFT)))
  821.     {
  822.       if ((mousex >= 0) && (mousex <= 5))
  823.       {
  824.         initsong(esnum, PLAY_BEGINNING);
  825.         followplay = shiftpressed;
  826.       }
  827.       if ((mousex >= 7) && (mousex <= 15))
  828.       {
  829.         initsong(esnum, PLAY_POS);
  830.         followplay = shiftpressed;
  831.       }
  832.       if ((mousex >= 17) && (mousex <= 26))
  833.       {
  834.         initsong(esnum, PLAY_PATTERN);
  835.         followplay = shiftpressed;
  836.       }
  837.       if ((mousex >= 28) && (mousex <= 33))
  838.         stopsong();
  839.       if ((mousex >= 35) && (mousex <= 40))
  840.         load();
  841.       if ((mousex >= 42) && (mousex <= 47))
  842.         save();
  843.       if ((mousex >= 49) && (mousex <= 57))
  844.         relocator();
  845.       if ((mousex >= 59) && (mousex <= 64))
  846.         onlinehelp(0,0);
  847.       if ((mousex >= 66) && (mousex <= 72))
  848.         clear();
  849.       if ((mousex >= 74) && (mousex <= 79))
  850.         quit();
  851.     }
  852.   }
  853. }
  854.  
  855. void generalcommands(void)
  856. {
  857.   int c;
  858.  
  859.   switch(key)
  860.   {
  861.     case '?':
  862.     case '-':
  863.     if ((editmode != EDIT_NAMES) && (editmode != EDIT_ORDERLIST))
  864.     {
  865.       if (!((editmode == EDIT_INSTRUMENT) && (eipos == 9))) previnstr();
  866.     }
  867.     break;
  868.  
  869.     case '+':
  870.     case '_':
  871.     if ((editmode != EDIT_NAMES) && (editmode != EDIT_ORDERLIST))
  872.     {
  873.       if (!((editmode == EDIT_INSTRUMENT) && (eipos >= 9))) nextinstr();
  874.  
  875.     }
  876.     break;
  877.  
  878.     case '*':
  879.     if (editmode != EDIT_NAMES)
  880.     {
  881.       if (!((editmode == EDIT_INSTRUMENT) && (eipos >= 9)))
  882.       {
  883.         if (epoctave < 7) epoctave++;
  884.       }
  885.     }
  886.     break;
  887.  
  888.     case '/':
  889.     case '\'':
  890.     if (editmode != EDIT_NAMES)
  891.     {
  892.       if (!((editmode == EDIT_INSTRUMENT) && (eipos >= 9)))
  893.       {
  894.         if (epoctave > 0) epoctave--;
  895.       }
  896.     }
  897.     break;
  898.  
  899.     case '<':
  900.     if (((editmode == EDIT_INSTRUMENT) && (eipos != 9)) || (editmode == EDIT_TABLES))
  901.       previnstr();
  902.     break;
  903.  
  904.     case '>':
  905.     if (((editmode == EDIT_INSTRUMENT) && (eipos != 9)) || (editmode == EDIT_TABLES))
  906.       nextinstr();
  907.     break;
  908.  
  909.     case ';':
  910.     for (c = 0; c < MAX_CHN; c++)
  911.     {
  912.       if (espos[c]) espos[c]--;
  913.       if (espos[c] < esview)
  914.       {
  915.         esview = espos[c];
  916.         eseditpos = espos[c];
  917.       }
  918.     }
  919.     updateviewtopos();
  920.     rewindsong();
  921.     break;
  922.  
  923.     case ':':
  924.     for (c = 0; c < MAX_CHN; c++)
  925.     {
  926.       if (espos[c] < songlen[esnum][c]-1)
  927.         espos[c]++;
  928.       if (espos[c] - esview >= VISIBLEORDERLIST)
  929.       {
  930.         esview = espos[c] - VISIBLEORDERLIST + 1;
  931.         eseditpos = espos[c];
  932.       }
  933.     }
  934.     updateviewtopos();
  935.     rewindsong();
  936.     break;
  937.  
  938.   }
  939.   if (win_quitted) exitprogram = 1;
  940.   switch(rawkey)
  941.   {
  942.     case KEY_ESC:
  943.     if (!shiftpressed)
  944.       quit();
  945.     else
  946.       clear();
  947.     break;
  948.  
  949.     case KEY_KPMULTIPLY:
  950.     if ((editmode != EDIT_NAMES) && (!key))
  951.     {
  952.       if (!((editmode == EDIT_INSTRUMENT) && (eipos >= 9)))
  953.       {
  954.         if (epoctave < 7) epoctave++;
  955.       }
  956.     }
  957.     break;
  958.  
  959.     case KEY_KPDIVIDE:
  960.     if ((editmode != EDIT_NAMES) && (!key))
  961.     {
  962.       if (!((editmode == EDIT_INSTRUMENT) && (eipos >= 9)))
  963.       {
  964.         if (epoctave > 0) epoctave--;
  965.       }
  966.     }
  967.     break;
  968.  
  969.     case KEY_F12:
  970.       onlinehelp(0,shiftpressed);
  971.     break;
  972.  
  973.     case KEY_TAB:
  974.     if (!shiftpressed) editmode++;
  975.     else editmode--;
  976.     if (editmode > EDIT_NAMES) editmode = EDIT_PATTERN;
  977.     if (editmode < EDIT_PATTERN) editmode = EDIT_NAMES;
  978.     break;
  979.  
  980.     case KEY_F1:
  981.     initsong(esnum, PLAY_BEGINNING);
  982.     followplay = shiftpressed;
  983.     break;
  984.  
  985.     case KEY_F2:
  986.     initsong(esnum, PLAY_POS);
  987.     followplay = shiftpressed;
  988.     break;
  989.  
  990.     case KEY_F3:
  991.     initsong(esnum, PLAY_PATTERN);
  992.     followplay = shiftpressed;
  993.     break;
  994.  
  995.     case KEY_F4:
  996.     if (shiftpressed)
  997.       mutechannel(epchn);
  998.     else
  999.     stopsong();
  1000.     break;
  1001.  
  1002.     case KEY_F5:
  1003.     if (!shiftpressed)
  1004.       editmode = EDIT_PATTERN;
  1005.     else prevmultiplier();
  1006.     break;
  1007.  
  1008.     case KEY_F6:
  1009.     if (!shiftpressed)
  1010.       editmode = EDIT_ORDERLIST;
  1011.     else nextmultiplier();
  1012.     break;
  1013.  
  1014.     case KEY_F7:
  1015.     if (!shiftpressed)
  1016.     {
  1017.       if (editmode == EDIT_INSTRUMENT)
  1018.         editmode = EDIT_TABLES;
  1019.       else
  1020.         editmode = EDIT_INSTRUMENT;
  1021.     }
  1022.     else editadsr();
  1023.     break;
  1024.  
  1025.     case KEY_F8:
  1026.     if (!shiftpressed)
  1027.       editmode = EDIT_NAMES;
  1028.     else
  1029.     {
  1030.       sidmodel ^= 1;
  1031.       sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate);
  1032.     }
  1033.     break;
  1034.  
  1035.     case KEY_F9:
  1036.     relocator();
  1037.     break;
  1038.  
  1039.     case KEY_F10:
  1040.     load();
  1041.     break;
  1042.  
  1043.     case KEY_F11:
  1044.     save();
  1045.     break;
  1046.   }
  1047. }
  1048.  
  1049. void load(void)
  1050. {
  1051.   if ((editmode != EDIT_INSTRUMENT) && (editmode != EDIT_TABLES))
  1052.   {
  1053.     if (fileselector(songfilename, songpath, songfilter, "LOAD SONG", 0))
  1054.       loadsong();
  1055.   }
  1056.   else
  1057.   {
  1058.     if (einum)
  1059.     {
  1060.       if (fileselector(instrfilename, instrpath, instrfilter, "LOAD INSTRUMENT", 0))
  1061.         loadinstrument();
  1062.     }
  1063.   }
  1064.   key = 0;
  1065.   rawkey = 0;
  1066. }
  1067.  
  1068. void save(void)
  1069. {
  1070.   if ((editmode != EDIT_INSTRUMENT) && (editmode != EDIT_TABLES))
  1071.   {
  1072.     int done = 0;
  1073.  
  1074.     // Repeat until quit or save successful
  1075.     while (!done)
  1076.     {
  1077.       if (strlen(loadedsongfilename)) strcpy(songfilename, loadedsongfilename);
  1078.       if (fileselector(songfilename, songpath, songfilter, "SAVE SONG", 3))
  1079.         done = savesong();
  1080.       else done = 1;
  1081.     }
  1082.   }
  1083.   else
  1084.   {
  1085.     if (einum)
  1086.     {
  1087.       int done = 0;
  1088.       int useinstrname = 0;
  1089.       char tempfilename[MAX_FILENAME];
  1090.  
  1091.       // Repeat until quit or save successful
  1092.       while (!done)
  1093.       {
  1094.         if ((!strlen(instrfilename)) && (strlen(instr[einum].name)))
  1095.         {
  1096.           useinstrname = 1;
  1097.           strcpy(instrfilename, instr[einum].name);
  1098.           strcat(instrfilename, ".ins");
  1099.           strcpy(tempfilename, instrfilename);
  1100.         }
  1101.  
  1102.         if (fileselector(instrfilename, instrpath, instrfilter, "SAVE INSTRUMENT", 3))
  1103.           done = saveinstrument();
  1104.         else done = 1;
  1105.  
  1106.         if (useinstrname)
  1107.         {
  1108.           if (!strcmp(tempfilename, instrfilename))
  1109.             memset(instrfilename, 0, sizeof instrfilename);
  1110.         }
  1111.       }
  1112.     }
  1113.   }
  1114.   key = 0;
  1115.   rawkey = 0;
  1116. }
  1117.  
  1118. void quit(void)
  1119. {
  1120.   if ((!shiftpressed) || (mouseb))
  1121.   {
  1122.     printtextcp(38, 36, 15, "Really Quit (y/n)?");
  1123.     waitkey();
  1124.     printblank(20, 36, 39);
  1125.     if ((key == 'y') || (key == 'Y')) exitprogram = 1;
  1126.   }
  1127.   key = 0;
  1128.   rawkey = 0;
  1129. }
  1130.  
  1131. void clear(void)
  1132. {
  1133.   int cs = 0;
  1134.   int cp = 0;
  1135.   int ci = 0;
  1136.   int ct = 0;
  1137.   int cn = 0;
  1138.  
  1139.   printtextcp(38, 36, 15, "Optimize everything (y/n)?");
  1140.   waitkey();
  1141.   printblank(20, 36, 39);
  1142.   if ((key == 'y') || (key == 'Y'))
  1143.   {
  1144.     optimizeeverything(1, 1);
  1145.     key = 0;
  1146.     rawkey = 0;
  1147.     return;
  1148.   }
  1149.  
  1150.   printtextcp(38, 36, 15, "Clear orderlists (y/n)?");
  1151.   waitkey();
  1152.   printblank(20, 36, 39);
  1153.   if ((key == 'y') || (key == 'Y')) cs = 1;
  1154.  
  1155.   printtextcp(38, 36, 15, "Clear patterns (y/n)?");
  1156.   waitkey();
  1157.   printblank(20, 36, 39);
  1158.   if ((key == 'y') || (key == 'Y')) cp = 1;
  1159.  
  1160.   printtextcp(38, 36, 15, "Clear instruments (y/n)?");
  1161.   waitkey();
  1162.   printblank(20, 36, 39);
  1163.   if ((key == 'y') || (key == 'Y')) ci = 1;
  1164.  
  1165.   printtextcp(38, 36, 15, "Clear tables (y/n)?");
  1166.   waitkey();
  1167.   printblank(20, 36, 39);
  1168.   if ((key == 'y') || (key == 'Y')) ct = 1;
  1169.  
  1170.   printtextcp(38, 36, 15, "Clear songname (y/n)?");
  1171.   waitkey();
  1172.   printblank(20, 36, 39);
  1173.   if ((key == 'y') || (key == 'Y')) cn = 1;
  1174.  
  1175.   if (cp == 1)
  1176.   {
  1177.     int selectdone = 0;
  1178.     int olddpl = defaultpatternlength;
  1179.  
  1180.     printtext(29, 36, 15,"Pattern length:");
  1181.     while (!selectdone)
  1182.     {
  1183.       sprintf(textbuffer, "%02d ", defaultpatternlength);
  1184.       printtext(44, 36, 15, textbuffer);
  1185.       waitkey();
  1186.       switch(rawkey)
  1187.       {
  1188.         case KEY_LEFT:
  1189.         defaultpatternlength -= 7;
  1190.         case KEY_DOWN:
  1191.         defaultpatternlength--;
  1192.         if (defaultpatternlength < 1) defaultpatternlength = 1;
  1193.         break;
  1194.  
  1195.         case KEY_RIGHT:
  1196.         defaultpatternlength += 7;
  1197.         case KEY_UP:
  1198.         defaultpatternlength++;
  1199.         if (defaultpatternlength > MAX_PATTROWS) defaultpatternlength = MAX_PATTROWS;
  1200.         break;
  1201.  
  1202.         case KEY_ESC:
  1203.         defaultpatternlength = olddpl;
  1204.         selectdone = 1;
  1205.         break;
  1206.  
  1207.         case KEY_ENTER:
  1208.         selectdone = 1;
  1209.         break;
  1210.       }
  1211.     }
  1212.     printblank(20, 36, 39);
  1213.   }
  1214.  
  1215.   if (cs | cp | ci | ct | cn)
  1216.     memset(songfilename, 0, sizeof songfilename);
  1217.   clearsong(cs, cp, ci, ct, cn);
  1218.  
  1219.   key = 0;
  1220.   rawkey = 0;
  1221. }
  1222.  
  1223.  
  1224. void editadsr(void)
  1225. {
  1226.   eamode = 1;
  1227.   eacolumn = 0;
  1228.  
  1229.   for (;;)
  1230.   {
  1231.     waitkeymouse();
  1232.  
  1233.     if (win_quitted)
  1234.     {
  1235.       exitprogram = 1;
  1236.       key = 0;
  1237.       rawkey = 0;
  1238.       return;
  1239.     }
  1240.  
  1241.     if (hexnybble >= 0)
  1242.     {
  1243.       switch(eacolumn)
  1244.       {
  1245.         case 0:
  1246.         adparam &= 0x0fff;
  1247.         adparam |= hexnybble << 12;
  1248.         break;
  1249.  
  1250.         case 1:
  1251.         adparam &= 0xf0ff;
  1252.         adparam |= hexnybble << 8;
  1253.         break;
  1254.  
  1255.         case 2:
  1256.         adparam &= 0xff0f;
  1257.         adparam |= hexnybble << 4;
  1258.         break;
  1259.  
  1260.         case 3:
  1261.         adparam &= 0xfff0;
  1262.         adparam |= hexnybble;
  1263.         break;
  1264.       }
  1265.       eacolumn++;
  1266.     }
  1267.  
  1268.     switch(rawkey)
  1269.     {
  1270.       case KEY_F7:
  1271.       if (!shiftpressed) break;
  1272.  
  1273.       case KEY_ESC:
  1274.       case KEY_ENTER:
  1275.       case KEY_TAB:
  1276.       eamode = 0;
  1277.       key = 0;
  1278.       rawkey = 0;
  1279.       return;
  1280.  
  1281.       case KEY_BACKSPACE:
  1282.       if (!eacolumn) break;
  1283.       case KEY_LEFT:
  1284.       eacolumn--;
  1285.       break;
  1286.  
  1287.       case KEY_RIGHT:
  1288.       eacolumn++;
  1289.     }
  1290.     eacolumn &= 3;
  1291.  
  1292.     if ((mouseb) && (!prevmouseb))
  1293.     {
  1294.       eamode = 0;
  1295.       return;
  1296.     }
  1297.   }
  1298. }
  1299.  
  1300. void getparam(FILE *handle, unsigned *value)
  1301. {
  1302.   char *configptr;
  1303.  
  1304.   for (;;)
  1305.   {
  1306.     if (feof(handle)) return;
  1307.     fgets(configbuf, MAX_PATHNAME, handle);
  1308.     if ((configbuf[0]) && (configbuf[0] != ';') && (configbuf[0] != ' ') && (configbuf[0] != 13) && (configbuf[0] != 10)) break;
  1309.   }
  1310.  
  1311.   configptr = configbuf;
  1312.   if (*configptr == '$')
  1313.   {
  1314.     *value = 0;
  1315.     configptr++;
  1316.     for (;;)
  1317.     {
  1318.       char c = tolower(*configptr++);
  1319.       int h = -1;
  1320.  
  1321.       if ((c >= 'a') && (c <= 'f')) h = c - 'a' + 10;
  1322.       if ((c >= '0') && (c <= '9')) h = c - '0';
  1323.  
  1324.       if (h >= 0)
  1325.       {
  1326.         *value *= 16;
  1327.         *value += h;
  1328.       }
  1329.       else break;
  1330.     }
  1331.   }
  1332.   else
  1333.   {
  1334.     *value = 0;
  1335.     for (;;)
  1336.     {
  1337.       char c = tolower(*configptr++);
  1338.       int d = -1;
  1339.  
  1340.       if ((c >= '0') && (c <= '9')) d = c - '0';
  1341.  
  1342.       if (d >= 0)
  1343.       {
  1344.         *value *= 10;
  1345.         *value += d;
  1346.       }
  1347.       else break;
  1348.     }
  1349.   }
  1350. }
  1351.  
  1352. void getfloatparam(FILE *handle, float *value)
  1353. {
  1354.   char *configptr;
  1355.  
  1356.   for (;;)
  1357.   {
  1358.     if (feof(handle)) return;
  1359.     fgets(configbuf, MAX_PATHNAME, handle);
  1360.     if ((configbuf[0]) && (configbuf[0] != ';') && (configbuf[0] != ' ') && (configbuf[0] != 13) && (configbuf[0] != 10)) break;
  1361.   }
  1362.  
  1363.   configptr = configbuf;
  1364.   *value = 0.0f;
  1365.   sscanf(configptr, "%f", value);
  1366. }
  1367.  
  1368. void prevmultiplier(void)
  1369. {
  1370.   if (multiplier > 0)
  1371.   {
  1372.     multiplier--;
  1373.     sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate);
  1374.   }
  1375. }
  1376.  
  1377. void nextmultiplier(void)
  1378. {
  1379.   if (multiplier < 16)
  1380.   {
  1381.     multiplier++;
  1382.     sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate);
  1383.   }
  1384. }
  1385.  
  1386. void calculatefreqtable()
  1387. {
  1388.   double basefreq = (double)basepitch * (16777216.0 / 985248.0) * pow(2.0, 0.25) / 32.0;
  1389.   int c;
  1390.  
  1391.   for (c = 0; c < 8*12 ; c++)
  1392.   {
  1393.     double note = c;
  1394.     double freq = basefreq * pow(2.0, note/12.0);
  1395.     int intfreq = freq + 0.5;
  1396.     if (intfreq > 0xffff)
  1397.         intfreq = 0xffff;
  1398.     freqtbllo[c] = intfreq & 0xff;
  1399.     freqtblhi[c] = intfreq >> 8;
  1400.   }
  1401. }
  1402.