home *** CD-ROM | disk | FTP | other *** search
/ Audio Version 4.94 / audioversion4.94knowledgemediaresourcelibraryoctober1994.iso / msdos / midi / k1patche / k1patche.sha / pe.c < prev   
C/C++ Source or Header  |  1994-03-16  |  44KB  |  1,760 lines

  1. #include <stdio.h>
  2.  
  3. char *st_copyright[] = {
  4. " *********************************************************************",
  5. " * Copyright 1989 by H. Edward Hall                                  *",
  6. " *                                                                   *",
  7. " * Permission is hereby granted to copy and to give away this        *",
  8. " * software as long as this notice is preserved in its entirety.     *",
  9. " * You may modify the software or use it for any purpose just as     *",
  10. " * long as you preserve this notice and do not sell the software.    *",
  11. " * No warranty of any kind is made for this software.  The holder    *",
  12. " * of this copyright reserves the right to enhance and/or sell       *",
  13. " * this software with no obligation to provide updates or further    *",
  14. " * free copies; if this should happen you may still use this version *",
  15. " * of the software under the terms you received it with.             *",
  16. " *********************************************************************",
  17.                                     NULL};
  18.  
  19. /*
  20.  * [That said, I expect subsequent versions to remain freeware
  21.  * unless starvation sets it.]
  22.  */
  23.  
  24. /*
  25.  * Kawai K-1 Patch Editor V0.1
  26.  *
  27.  * This editor is a first (and only slightly successful) attempt
  28.  * to make a hardware-independent patch editor.  I expect a great
  29.  * deal more evolution will take place as I adapt it for the
  30.  * Yamaha DX-7II (almost finished!) and other synths.
  31.  *
  32.  * The features are currently rather sparse, but certainly an order
  33.  * of magnitude better than using Kawai's user interface.
  34.  */
  35.  
  36. /*
  37.  * Patch parameter descriptor structure
  38.  */
  39. struct param
  40. {
  41.     unsigned char p_flags;          /* special attributes of this field */
  42.     unsigned char p_type;           /* data conversion for this field */
  43.     unsigned char p_byte;           /* byte within patch */
  44.     unsigned char p_bit;            /* starting bit within byte */
  45.     unsigned char p_nbits;          /* number of bits in field */
  46.     unsigned char p_secbyte;        /* secondary byte within patch */
  47.     unsigned char p_secbit;         /* starting bit within byte */
  48.     unsigned char p_secnbits;       /* number of bits in field */
  49.     unsigned char p_row;            /* row on display screen */
  50.     unsigned char p_col;            /* column on display screen */
  51.     int p_bias;                     /* minimum value */
  52.     int p_limit;                    /* maximum value */
  53.     char **p_names;                 /* strings for ENUM type */
  54. };
  55.  
  56. /*
  57.  * Enumeration strings for SINGLE display
  58.  */
  59. char *st_src[] = {"2", "4"};
  60. char *st_poly[] = {"Poly-1", "Poly-2", "Solo  "};
  61. char *st_am12[] = {"off", "1>2", "2>1"};
  62. char *st_am34[] = {"off", "3>4", "4>3"};
  63. char *st_vshp[] = {"TRI", "SAW", "SQR", "RND"};
  64. char *st_vwhl[] = {"DEP", "SPD"};
  65. char *st_mute[] = {" ", "*"};
  66. char *st_trkg[] = {"No ", "Yes"};
  67. char *st_onof[] = {"off", "On "};
  68. char *st_wave[] =
  69. {"  1 Sin 1st   ", "  2 Sin 2nd   ", "  3 Sin 3rd   ", "  4 Sin 4th   ",
  70.  "  5 Sin 5th   ", "  6 Sin 6th   ", "  7 Sin 7th   ", "  8 Sin 8th   ",
  71.  "  9 Sin 9th   ", " 10 Sin 10th  ", " 11 Sin 11th  ", " 12 Sin 12th  ",
  72.  " 13 Sin 16th  ", " 14 Saw 1     ", " 15 Saw 2     ", " 16 Saw 3     ",
  73.  " 17 Saw 4     ", " 18 Saw 5     ", " 19 Saw 6     ", " 20 Saw 7     ",
  74.  " 21 Saw 8     ", " 22 Saw 9     ", " 23 Saw 10    ", " 24 Saw 11    ",
  75.  " 25 Saw 12    ", " 26 Saw 13    ", " 27 Saw 14    ", " 28 Saw 15    ",
  76.  " 29 Saw 16    ", " 30 Saw 17    ", " 31 Saw 18    ", " 32 Saw 19    ",
  77.  " 33 Square 1  ", " 34 Square 2  ", " 35 Square 3  ", " 36 Square 4  ",
  78.  " 37 Square 5  ", " 38 Invrse Saw", " 39 Triangle  ", " 40 Random    ",
  79.  " 41 Frnch Horn", " 42 String 1  ", " 43 String 2  ", " 44 String Pad",
  80.  " 45 Piano 1   ", " 46 El. Grand ", " 47 E. Piano 1", " 48 E. Piano 2",
  81.  " 49 E. Piano 3", " 50 Clavi     ", " 51 Vibe      ", " 52 A. Guitar ",
  82.  " 53 F. Guitar ", " 54 F. Guitar ", " 55 A. Bass   ", " 56 A. Bass   ",
  83.  " 57 Dig Bass 1", " 58 Pick Bass ", " 59 Dig Bass 2", " 60 Round Bass",
  84.  " 61 Fretless 1", " 62 Fretless 2", " 63 Flute     ", " 64 Pan Flute ",
  85.  " 65 Harmonica ", " 66 Glocken   ", " 67 Tine      ", " 68 Harp      ",
  86.  " 69 Marimba   ", " 70 E. Tom    ", " 71 Log Drum  ", " 72 Jazz Org 1",
  87.  " 73 Mello Pad ", " 74 Synth Solo", " 75 Synth 2   ", " 76 Frnch Horn",
  88.  " 77 Frnch Horn", " 78 Brass     ", " 79 Brass     ", " 80 Brass     ",
  89.  " 81 Brass     ", " 82 Trumpet   ", " 83 Trumpet   ", " 84 Violin    ",
  90.  " 85 String    ", " 86 Piano 1   ", " 87 Piano 2   ", " 88 Piano 3   ",
  91.  " 89 Piano 2   ", " 90 Piano 3   ", " 91 Piano 4   ", " 92 Piano 4   ",
  92.  " 93 El. Grand ", " 94 E. Piano 1", " 95 E. Piano 2", " 96 E. Piano 2",
  93.  " 97 Clavi     ", " 98 Harpschord", " 99 Vibe      ", "100 A. Guitar ",
  94.  "101 F. Guitar ", "102 Strat     ", "103 Strat     ", "104 A. Bass   ",
  95.  "105 Pull Bass ", "106 Pull Bass ", "107 Round Bass", "108 Slap Bass ",
  96.  "109 Slap Bass ", "110 Slap Bass ", "111 Fretless  ", "112 Fretless  ",
  97.  "113 Synth Bass", "114 Synth Bass", "115 Harmonica ", "116 Clarinet  ",
  98.  "117 Clarinet  ", "118 Oboe      ", "119 Oboe      ", "120 Shakuhachi",
  99.  "121 Orient Bel", "122 Orient Bel", "123 Bell      ", "124 Koto      ",
  100.  "125 Sitar     ", "126 E. Tom    ", "127 Log Drum  ", "128 Log Drum  ",
  101.  "129 Steel Drum", "130 Steel Drum", "131 Voice 1   ", "132 Voice 2   ",
  102.  "133 Accordion ", "134 Accordion ", "135 Jazz Org 2", "136 Rock Org 1",
  103.  "137 Draw Bar 1", "138 Draw Bar 2", "139 Pipe Org 1", "140 Pipe Org 2",
  104.  "141 Rock Org 2", "142 Synth Solo", "143 Synth Solo", "144 Synth 2   ",
  105.  "145 Synth 2   ", "146 Synth 3   ", "147 Brass     ", "148 Brass     ",
  106.  "149 Orchestra ", "150 Piano 1   ", "151 Piano 4   ", "152 E. Piano 1",
  107.  "153 E. Piano 1", "154 E. Piano 2", "155 E. Piano 3", "156 Clavi     ",
  108.  "157 Harpschord", "158 Harpschord", "159 Vibe      ", "160 Dig Bass 1",
  109.  "161 Dig Bass 2", "162 Dig Bass 2", "163 Pick bass ", "164 Glocken   ",
  110.  "165 Glocken   ", "166 Tine      ", "167 Tine      ", "168 Tine      ",
  111.  "169 Tube Bell ", "170 Tube Bell ", "171 Tube Bell ", "172 Xylophone ",
  112.  "173 Xylophone ", "174 Harp      ", "175 Koto      ", "176 Sitar     ",
  113.  "177 Sitar     ", "178 Kalimbra  ", "179 Kalimbra  ", "180 Kalimbra  ",
  114.  "181 Log Drum  ", "182 Steel Drum", "183 Pipe Org 3", "184 Pipe Org 3",
  115.  "185 Synth 1   ", "186 Synth 2   ", "187 Synth 3   ", "188 Synth 3   ",
  116.  "189 Synth 4   ", "190 Synth 4   ", "191 Clavi     ", "192 Dig Bass 1",
  117.  "193 Dig Bass 1", "194 Pick Bass ", "195 Pick Bass ", "196 Round Bass",
  118.  "197 Round Bass", "198 Harmonica ", "199 Harmonica ", "200 Harp      ",
  119.  "201 Koto      ", "202 Sitar     ", "203 Marimba   ", "204 Synth 1   ",
  120.  "205 Bass Drum ", "206 A. Snare  ", "207 Tite Snare", "208 E. Snare  ",
  121.  "209 Rim       ", "210 A. Tom    ", "211 High Hat  ", "212 Crash     ",
  122.  "213 Ride      ", "214 Strat Guit", "215 Fuzz Mute ", "216 A. Guitar ",
  123.  "217 F. Guitar ", "218 Guit Harmo", "219 Pull Bass ", "220 Bass Harmo",
  124.  "221 Bowd Strng", "222 Strng Attk", "223 String Sus", "224 Pizzicato ",
  125.  "225 Piano     ", "226 El. Grand ", "227 Piano Nois", "228 Trumpet   ",
  126.  "229 Shak Attck", "230 Shak Sustn", "231 PanFl Attk", "232 PanFl Sust",
  127.  "233 Voice     ", "234 White Nois", "235 Strng Loop", "236 Shak Loop ",
  128.  "237 PanFl Loop", "238 Voice Loop", "239 WhtNois Lp", "240 Snare Loop",
  129.  "241 F. Guit Lp", "242 PulBass Lp", "243 OmniLoop 1", "244 OmniLoop 2",
  130.  "245 OmniLoop 3", "246 OmniLoop 4", "247 OmniLoop 5", "248 OmniLoop 6",
  131.  "249 OmniLoop 7", "250 OmniLoop 8", "251 Snare Rev ", "252 Tom Rev   ",
  132.  "253 F. Guit Rv", "254 Hi Hat Alt", "255 Crash Alt ", "256 PnoNois Al"};
  133.  
  134. char *st_note[] =
  135. {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
  136.  
  137.  
  138. /*
  139.  * data types
  140.  */
  141. #define LSTR 1          /* literal string */
  142. #define ENUM 2          /* enumeration */
  143. #define SNUM 3          /* signed number */
  144. #define UNUM 4          /* unsigned number */
  145. #define SPL1 5          /* coarse frequency display */
  146. #define SPL2 6          /* SINGLE name */
  147. #define SPL3 7          /* MIDI note name */
  148. #define PEND 15         /* end-of-parameters sentinel */
  149. #define FNRM 0x00       /* normal flag */
  150. #define FSC4 0x10       /* display only if SRC == 4 */
  151. #define FSGL 0x20       /* SINGLE component of a MULTIPLE */
  152. #define G(x) (FSGL|x)   /* a specific SINGLE component */
  153. #define FRDW 0x40       /* redraw if value changed */
  154.  
  155. /*
  156.  * SINGLE parameter list
  157.  */
  158. struct param params[] =
  159. {       {FNRM, LSTR,   0, 0, 8,  0, 0, 0,  1, 21,   0,  10, NULL},
  160.     {FRDW, ENUM,  11, 2, 1,  0, 0, 0,  1, 39,   0,   1, st_src},
  161.     {FNRM, UNUM,  10, 0, 8,  0, 0, 0,  1, 47,   0, 100, NULL},
  162.     {FNRM, ENUM,  11, 0, 2,  0, 0, 0,  1, 53,   0,   2, st_poly},
  163.     {FNRM, ENUM,  11, 3, 2,  0, 0, 0,  1, 65,   0,   2, st_am12},
  164.     {FNRM, ENUM,  11, 5, 2,  0, 0, 0,  1, 74,   0,   2, st_am34},
  165.     {FNRM, SNUM,  13, 0, 8,  0, 0, 0,  2, 23, -50,  50, NULL},
  166.     {FNRM, UNUM,  16, 0, 8,  0, 0, 0,  2, 35,   0, 100, NULL},
  167.     {FNRM, ENUM,  17, 0, 2,  0, 0, 0,  2, 50,   0,   3, st_vshp},
  168.     {FNRM, SNUM,  14, 0, 8,  0, 0, 0,  2, 63, -50,  50, NULL},
  169.     {FNRM, ENUM,  17, 5, 2,  0, 0, 0,  2, 75,   0,   1, st_vwhl},
  170.     {FNRM, UNUM,  17, 2, 3,  0, 0, 0,  3,  7,   1,   5, NULL},
  171.     {FNRM, SNUM,  18, 0, 8,  0, 0, 0,  3, 23, -50,  50, NULL},
  172.     {FNRM, UNUM,  19, 0, 8,  0, 0, 0,  3, 34,   0, 100, NULL},
  173.     {FNRM, SNUM,  20, 0, 8,  0, 0, 0,  3, 45, -50,  50, NULL},
  174.     {FNRM, SNUM,  21, 0, 8,  0, 0, 0,  3, 54, -50,  50, NULL},
  175.     {FNRM, SNUM,  12, 0, 8,  0, 0, 0,  3, 63, -50,  50, NULL},
  176.     {FNRM, UNUM,  15, 0, 4,  0, 0, 0,  3, 75,   0,  12, NULL},
  177. /*S1*/  {FNRM, ENUM,  22, 0, 1,  0, 0, 0,  5,  3,   0,   1, st_mute},
  178.     {FNRM, ENUM,  31, 0, 7, 35, 0, 1,  5,  9,   0, 255, st_wave},
  179.     {FNRM, ENUM,  35, 1, 1,  0, 0, 0,  5, 25,   0,   1, st_trkg},
  180.     {FNRM, SPL1,  27, 0, 8,  0, 0, 0,  5, 33,   0, 127, NULL},
  181.     {FNRM, SNUM,  23, 0, 8,  0, 0, 0,  5, 39, -50,  50, NULL},
  182.     {FNRM, SNUM,  83, 0, 8,  0, 0, 0,  5, 44, -50,  50, NULL},
  183.     {FNRM, ENUM,  35, 2, 1,  0, 0, 0,  5, 49,   0,   1, st_onof},
  184.     {FNRM, ENUM,  35, 3, 1,  0, 0, 0,  5, 54,   0,   1, st_onof},
  185. /*S2*/  {FNRM, ENUM,  22, 1, 1,  0, 0, 0,  6,  3,   0,   1, st_mute},
  186.     {FNRM, ENUM,  32, 0, 7, 36, 0, 1,  6,  9,   0, 255, st_wave},
  187.     {FNRM, ENUM,  36, 1, 1,  0, 0, 0,  6, 25,   0,   1, st_trkg},
  188.     {FNRM, SPL1,  28, 0, 8,  0, 0, 0,  6, 33,   0, 127, NULL},
  189.     {FNRM, SNUM,  24, 0, 8,  0, 0, 0,  6, 39, -50,  50, NULL},
  190.     {FNRM, SNUM,  84, 0, 8,  0, 0, 0,  6, 44, -50,  50, NULL},
  191.     {FNRM, ENUM,  36, 2, 1,  0, 0, 0,  6, 49,   0,   1, st_onof},
  192.     {FNRM, ENUM,  36, 3, 1,  0, 0, 0,  6, 54,   0,   1, st_onof},
  193. /*S3*/  {FSC4, ENUM,  22, 2, 1,  0, 0, 0,  7,  3,   0,   1, st_mute},
  194.     {FSC4, ENUM,  33, 0, 7, 37, 0, 1,  7,  9,   0, 255, st_wave},
  195.     {FSC4, ENUM,  37, 1, 1,  0, 0, 0,  7, 25,   0,   1, st_trkg},
  196.     {FSC4, SPL1,  29, 0, 8,  0, 0, 0,  7, 33,   0, 127, NULL},
  197.     {FSC4, SNUM,  25, 0, 8,  0, 0, 0,  7, 39, -50,  50, NULL},
  198.     {FSC4, SNUM,  85, 0, 8,  0, 0, 0,  7, 44, -50,  50, NULL},
  199.     {FSC4, ENUM,  37, 2, 1,  0, 0, 0,  7, 49,   0,   1, st_onof},
  200.     {FSC4, ENUM,  37, 3, 1,  0, 0, 0,  7, 54,   0,   1, st_onof},
  201. /*S4*/  {FSC4, ENUM,  22, 3, 1,  0, 0, 0,  8,  3,   0,   1, st_mute},
  202.     {FSC4, ENUM,  34, 0, 7, 38, 0, 1,  8,  9,   0, 255, st_wave},
  203.     {FSC4, ENUM,  38, 1, 1,  0, 0, 0,  8, 25,   0,   1, st_trkg},
  204.     {FSC4, SPL1,  30, 0, 8,  0, 0, 0,  8, 33,   0, 127, NULL},
  205.     {FSC4, SNUM,  26, 0, 8,  0, 0, 0,  8, 39, -50,  50, NULL},
  206.     {FSC4, SNUM,  86, 0, 8,  0, 0, 0,  8, 44, -50,  50, NULL},
  207.     {FSC4, ENUM,  38, 2, 1,  0, 0, 0,  8, 49,   0,   1, st_onof},
  208.     {FSC4, ENUM,  38, 3, 1,  0, 0, 0,  8, 54,   0,   1, st_onof},
  209. /*S1*/  {FNRM, UNUM,  39, 0, 8,  0, 0, 0, 10, 11,   0, 100, NULL},
  210.     {FNRM, UNUM,  43, 0, 8,  0, 0, 0, 10, 15,   0, 100, NULL},
  211.     {FNRM, UNUM,  47, 0, 8,  0, 0, 0, 10, 19,   0, 100, NULL},
  212.     {FNRM, UNUM,  51, 0, 8,  0, 0, 0, 10, 23,   0, 100, NULL},
  213.     {FNRM, UNUM,  55, 0, 8,  0, 0, 0, 10, 27,   0, 100, NULL},
  214.     {FNRM, UNUM,  59, 0, 8,  0, 0, 0, 10, 31,   0, 100, NULL},
  215.     {FNRM, SNUM,  63, 0, 8,  0, 0, 0, 10, 36, -50,  50, NULL},
  216.     {FNRM, UNUM,  35, 4, 3,  0, 0, 0, 10, 43,   1,   8, NULL},
  217.     {FNRM, SNUM,  67, 0, 8,  0, 0, 0, 10, 48, -50,  50, NULL},
  218.     {FNRM, SNUM,  71, 0, 8,  0, 0, 0, 10, 55, -50,  50, NULL},
  219.     {FNRM, SNUM,  75, 0, 8,  0, 0, 0, 10, 62, -50,  50, NULL},
  220.     {FNRM, SNUM,  79, 0, 8,  0, 0, 0, 10, 68, -50,  50, NULL},
  221. /*S2*/  {FNRM, UNUM,  40, 0, 8,  0, 0, 0, 11, 11,   0, 100, NULL},
  222.     {FNRM, UNUM,  44, 0, 8,  0, 0, 0, 11, 15,   0, 100, NULL},
  223.     {FNRM, UNUM,  48, 0, 8,  0, 0, 0, 11, 19,   0, 100, NULL},
  224.     {FNRM, UNUM,  52, 0, 8,  0, 0, 0, 11, 23,   0, 100, NULL},
  225.     {FNRM, UNUM,  56, 0, 8,  0, 0, 0, 11, 27,   0, 100, NULL},
  226.     {FNRM, UNUM,  60, 0, 8,  0, 0, 0, 11, 31,   0, 100, NULL},
  227.     {FNRM, SNUM,  64, 0, 8,  0, 0, 0, 11, 36, -50,  50, NULL},
  228.     {FNRM, UNUM,  36, 4, 3,  0, 0, 0, 11, 43,   1,   8, NULL},
  229.     {FNRM, SNUM,  68, 0, 8,  0, 0, 0, 11, 48, -50,  50, NULL},
  230.     {FNRM, SNUM,  72, 0, 8,  0, 0, 0, 11, 55, -50,  50, NULL},
  231.     {FNRM, SNUM,  76, 0, 8,  0, 0, 0, 11, 62, -50,  50, NULL},
  232.     {FNRM, SNUM,  80, 0, 8,  0, 0, 0, 11, 68, -50,  50, NULL},
  233. /*S3*/  {FSC4, UNUM,  41, 0, 8,  0, 0, 0, 12, 11,   0, 100, NULL},
  234.     {FSC4, UNUM,  45, 0, 8,  0, 0, 0, 12, 15,   0, 100, NULL},
  235.     {FSC4, UNUM,  49, 0, 8,  0, 0, 0, 12, 19,   0, 100, NULL},
  236.     {FSC4, UNUM,  53, 0, 8,  0, 0, 0, 12, 23,   0, 100, NULL},
  237.     {FSC4, UNUM,  57, 0, 8,  0, 0, 0, 12, 27,   0, 100, NULL},
  238.     {FSC4, UNUM,  61, 0, 8,  0, 0, 0, 12, 31,   0, 100, NULL},
  239.     {FSC4, SNUM,  65, 0, 8,  0, 0, 0, 12, 36, -50,  50, NULL},
  240.     {FSC4, UNUM,  37, 4, 3,  0, 0, 0, 12, 43,   1,   8, NULL},
  241.     {FSC4, SNUM,  69, 0, 8,  0, 0, 0, 12, 48, -50,  50, NULL},
  242.     {FSC4, SNUM,  73, 0, 8,  0, 0, 0, 12, 55, -50,  50, NULL},
  243.     {FSC4, SNUM,  77, 0, 8,  0, 0, 0, 12, 62, -50,  50, NULL},
  244.     {FSC4, SNUM,  81, 0, 8,  0, 0, 0, 12, 68, -50,  50, NULL},
  245. /*S4*/  {FSC4, UNUM,  42, 0, 8,  0, 0, 0, 13, 11,   0, 100, NULL},
  246.     {FSC4, UNUM,  46, 0, 8,  0, 0, 0, 13, 15,   0, 100, NULL},
  247.     {FSC4, UNUM,  50, 0, 8,  0, 0, 0, 13, 19,   0, 100, NULL},
  248.     {FSC4, UNUM,  54, 0, 8,  0, 0, 0, 13, 23,   0, 100, NULL},
  249.     {FSC4, UNUM,  58, 0, 8,  0, 0, 0, 13, 27,   0, 100, NULL},
  250.     {FSC4, UNUM,  62, 0, 8,  0, 0, 0, 13, 31,   0, 100, NULL},
  251.     {FSC4, SNUM,  66, 0, 8,  0, 0, 0, 13, 36, -50,  50, NULL},
  252.     {FSC4, UNUM,  38, 4, 3,  0, 0, 0, 13, 43,   1,   8, NULL},
  253.     {FSC4, SNUM,  70, 0, 8,  0, 0, 0, 13, 48, -50,  50, NULL},
  254.     {FSC4, SNUM,  74, 0, 8,  0, 0, 0, 13, 55, -50,  50, NULL},
  255.     {FSC4, SNUM,  78, 0, 8,  0, 0, 0, 13, 62, -50,  50, NULL},
  256.     {FSC4, SNUM,  82, 0, 8,  0, 0, 0, 13, 68, -50,  50, NULL},
  257.     {FNRM, PEND,   0, 0, 0,  0, 0, 0,  0,  0,   0,   0, NULL}};
  258.  
  259. /*
  260.  * MULTIPLE enumeration strings
  261.  */
  262. char *st_vlsw[] = {"All ", "Soft", "Loud"};
  263. char *st_mmod[] = {"Kybd", "Midi", "Mix "};
  264. char *st_chan[] = {"R  ", "L+R", "L  "};
  265. char *st_mply[] = {"VR", "0 ", "1 ", "2 ", "3 ", "4 ", "5 ", "6 ", "7 ", "8 "};
  266.  
  267. /*
  268. 000000000111111111122222222223333333333444444444455555555556666666666777777
  269. 123456789012345678901234567890123456789012345678901234567890123456789012345
  270.       Source       Levl Tran Tune Out Poly Chan ZnLo ZnHi VSwch Mode
  271. S1 IA-1 xxxxxxxxxx 100  -24  -50  L+R  VR   1   127  127  Loud  MIDI
  272. */
  273. /*
  274.  * MULTIPLE parameter list
  275.  */
  276. struct param mparams[] = {
  277.     {FNRM, LSTR,   0, 0, 8,  0, 0, 0, 15, 23,   0,  10, NULL},
  278.     {FNRM, UNUM,  10, 0, 8,  0, 0, 0, 15, 43,   1, 100, NULL},
  279. /*S1*/  {G(1), SPL2,  11, 0, 6,  0, 0, 0, 17,  4,   0,  63, NULL},
  280.     {G(1), UNUM,  67, 0, 8,  0, 0, 0, 17, 20,   0, 100, NULL},
  281.     {G(1), SNUM,  51, 0, 6,  0, 0, 0, 17, 25, -24,  24, NULL},
  282.     {G(1), SNUM,  59, 0, 8,  0, 0, 0, 17, 30, -50,  50, NULL},
  283.     {G(1), ENUM,  35, 4, 2,  0, 0, 0, 17, 35,   0,   2, st_chan},
  284.     {FRDW, ENUM,  35, 0, 4,  0, 0, 0, 17, 40,   0,   9, st_mply},
  285.     {G(1), UNUM,  43, 0, 4,  0, 0, 0, 17, 45,   1,  16, NULL},
  286.     {G(1), SPL3,  19, 0, 8,  0, 0, 0, 17, 49,   0, 127, NULL},
  287.     {G(1), SPL3,  27, 0, 8,  0, 0, 0, 17, 54,   0, 127, NULL},
  288.     {G(1), ENUM,  43, 4, 2,  0, 0, 0, 17, 59,   0,   2, st_vlsw},
  289.     {G(1), ENUM,  35, 6, 1, 43, 6, 1, 17, 65,   0,   2, st_mmod},
  290. /*S2*/  {G(2), SPL2,  12, 0, 6,  0, 0, 0, 18,  4,   0,  63, NULL},
  291.     {G(2), UNUM,  68, 0, 8,  0, 0, 0, 18, 20,   0, 100, NULL},
  292.     {G(2), SNUM,  52, 0, 6,  0, 0, 0, 18, 25, -24,  24, NULL},
  293.     {G(2), SNUM,  60, 0, 8,  0, 0, 0, 18, 30, -50,  50, NULL},
  294.     {G(2), ENUM,  36, 4, 2,  0, 0, 0, 18, 35,   0,   2, st_chan},
  295.     {FRDW, ENUM,  36, 0, 4,  0, 0, 0, 18, 40,   0,   9, st_mply},
  296.     {G(2), UNUM,  44, 0, 4,  0, 0, 0, 18, 45,   1,  16, NULL},
  297.     {G(2), SPL3,  20, 0, 8,  0, 0, 0, 18, 49,   0, 127, NULL},
  298.     {G(2), SPL3,  28, 0, 8,  0, 0, 0, 18, 54,   0, 127, NULL},
  299.     {G(2), ENUM,  44, 4, 2,  0, 0, 0, 18, 59,   0,   2, st_vlsw},
  300.     {G(2), ENUM,  36, 6, 1, 44, 6, 1, 18, 65,   0,   2, st_mmod},
  301. /*S3*/  {G(3), SPL2,  13, 0, 6,  0, 0, 0, 19,  4,   0,  63, NULL},
  302.     {G(3), UNUM,  69, 0, 8,  0, 0, 0, 19, 20,   0, 100, NULL},
  303.     {G(3), SNUM,  53, 0, 6,  0, 0, 0, 19, 25, -24,  24, NULL},
  304.     {G(3), SNUM,  61, 0, 8,  0, 0, 0, 19, 30, -50,  50, NULL},
  305.     {G(3), ENUM,  37, 4, 2,  0, 0, 0, 19, 35,   0,   2, st_chan},
  306.     {FRDW, ENUM,  37, 0, 4,  0, 0, 0, 19, 40,   0,   9, st_mply},
  307.     {G(3), UNUM,  45, 0, 4,  0, 0, 0, 19, 45,   1,  16, NULL},
  308.     {G(3), SPL3,  21, 0, 8,  0, 0, 0, 19, 49,   0, 127, NULL},
  309.     {G(3), SPL3,  29, 0, 8,  0, 0, 0, 19, 54,   0, 127, NULL},
  310.     {G(3), ENUM,  45, 4, 2,  0, 0, 0, 19, 59,   0,   2, st_vlsw},
  311.     {G(3), ENUM,  37, 6, 1, 45, 6, 1, 19, 65,   0,   2, st_mmod},
  312. /*S4*/  {G(4), SPL2,  14, 0, 6,  0, 0, 0, 20,  4,   0,  63, NULL},
  313.     {G(4), UNUM,  70, 0, 8,  0, 0, 0, 20, 20,   0, 100, NULL},
  314.     {G(4), SNUM,  54, 0, 6,  0, 0, 0, 20, 25, -24,  24, NULL},
  315.     {G(4), SNUM,  62, 0, 8,  0, 0, 0, 20, 30, -50,  50, NULL},
  316.     {G(4), ENUM,  38, 4, 2,  0, 0, 0, 20, 35,   0,   2, st_chan},
  317.     {FRDW, ENUM,  38, 0, 4,  0, 0, 0, 20, 40,   0,   9, st_mply},
  318.     {G(4), UNUM,  46, 0, 4,  0, 0, 0, 20, 45,   1,  16, NULL},
  319.     {G(4), SPL3,  22, 0, 8,  0, 0, 0, 20, 49,   0, 127, NULL},
  320.     {G(4), SPL3,  30, 0, 8,  0, 0, 0, 20, 54,   0, 127, NULL},
  321.     {G(4), ENUM,  46, 4, 2,  0, 0, 0, 20, 59,   0,   2, st_vlsw},
  322.     {G(4), ENUM,  38, 6, 1, 46, 6, 1, 20, 65,   0,   2, st_mmod},
  323. /*S5*/  {G(5), SPL2,  15, 0, 6,  0, 0, 0, 21,  4,   0,  63, NULL},
  324.     {G(5), UNUM,  71, 0, 8,  0, 0, 0, 21, 20,   0, 100, NULL},
  325.     {G(5), SNUM,  55, 0, 6,  0, 0, 0, 21, 25, -24,  24, NULL},
  326.     {G(5), SNUM,  63, 0, 8,  0, 0, 0, 21, 30, -50,  50, NULL},
  327.     {G(5), ENUM,  39, 4, 2,  0, 0, 0, 21, 35,   0,   2, st_chan},
  328.     {FRDW, ENUM,  39, 0, 4,  0, 0, 0, 21, 40,   0,   9, st_mply},
  329.     {G(5), UNUM,  47, 0, 4,  0, 0, 0, 21, 45,   1,  16, NULL},
  330.     {G(5), SPL3,  23, 0, 8,  0, 0, 0, 21, 49,   0, 127, NULL},
  331.     {G(5), SPL3,  31, 0, 8,  0, 0, 0, 21, 54,   0, 127, NULL},
  332.     {G(5), ENUM,  47, 4, 2,  0, 0, 0, 21, 59,   0,   2, st_vlsw},
  333.     {G(5), ENUM,  39, 6, 1, 47, 6, 1, 21, 65,   0,   2, st_mmod},
  334. /*S6*/  {G(6), SPL2,  16, 0, 6,  0, 0, 0, 22,  4,   0,  63, NULL},
  335.     {G(6), UNUM,  72, 0, 8,  0, 0, 0, 22, 20,   0, 100, NULL},
  336.     {G(6), SNUM,  56, 0, 6,  0, 0, 0, 22, 25, -24,  24, NULL},
  337.     {G(6), SNUM,  64, 0, 8,  0, 0, 0, 22, 30, -50,  50, NULL},
  338.     {G(6), ENUM,  40, 4, 2,  0, 0, 0, 22, 35,   0,   2, st_chan},
  339.     {FRDW, ENUM,  40, 0, 4,  0, 0, 0, 22, 40,   0,   9, st_mply},
  340.     {G(6), UNUM,  48, 0, 4,  0, 0, 0, 22, 45,   1,  16, NULL},
  341.     {G(6), SPL3,  24, 0, 8,  0, 0, 0, 22, 49,   0, 127, NULL},
  342.     {G(6), SPL3,  32, 0, 8,  0, 0, 0, 22, 54,   0, 127, NULL},
  343.     {G(6), ENUM,  48, 4, 2,  0, 0, 0, 22, 59,   0,   2, st_vlsw},
  344.     {G(6), ENUM,  40, 6, 1, 48, 6, 1, 22, 65,   0,   2, st_mmod},
  345. /*S7*/  {G(7), SPL2,  17, 0, 6,  0, 0, 0, 23,  4,   0,  63, NULL},
  346.     {G(7), UNUM,  73, 0, 8,  0, 0, 0, 23, 20,   0, 100, NULL},
  347.     {G(7), SNUM,  57, 0, 6,  0, 0, 0, 23, 25, -24,  24, NULL},
  348.     {G(7), SNUM,  65, 0, 8,  0, 0, 0, 23, 30, -50,  50, NULL},
  349.     {G(7), ENUM,  41, 4, 2,  0, 0, 0, 23, 35,   0,   2, st_chan},
  350.     {FRDW, ENUM,  41, 0, 4,  0, 0, 0, 23, 40,   0,   9, st_mply},
  351.     {G(7), UNUM,  49, 0, 4,  0, 0, 0, 23, 45,   1,  16, NULL},
  352.     {G(7), SPL3,  25, 0, 8,  0, 0, 0, 23, 49,   0, 127, NULL},
  353.     {G(7), SPL3,  33, 0, 8,  0, 0, 0, 23, 54,   0, 127, NULL},
  354.     {G(7), ENUM,  49, 4, 2,  0, 0, 0, 23, 59,   0,   2, st_vlsw},
  355.     {G(7), ENUM,  41, 6, 1, 49, 6, 1, 23, 65,   0,   2, st_mmod},
  356. /*S8*/  {G(8), SPL2,  18, 0, 6,  0, 0, 0, 24,  4,   0,  63, NULL},
  357.     {G(8), UNUM,  74, 0, 8,  0, 0, 0, 24, 20,   0, 100, NULL},
  358.     {G(8), SNUM,  58, 0, 6,  0, 0, 0, 24, 25, -24,  24, NULL},
  359.     {G(8), SNUM,  66, 0, 8,  0, 0, 0, 24, 30, -50,  50, NULL},
  360.     {G(8), ENUM,  42, 4, 2,  0, 0, 0, 24, 35,   0,   2, st_chan},
  361.     {FRDW, ENUM,  42, 0, 4,  0, 0, 0, 24, 40,   0,   9, st_mply},
  362.     {G(8), UNUM,  50, 0, 4,  0, 0, 0, 24, 45,   1,  16, NULL},
  363.     {G(8), SPL3,  26, 0, 8,  0, 0, 0, 24, 49,   0, 127, NULL},
  364.     {G(8), SPL3,  34, 0, 8,  0, 0, 0, 24, 54,   0, 127, NULL},
  365.     {G(8), ENUM,  50, 4, 2,  0, 0, 0, 24, 59,   0,   2, st_vlsw},
  366.     {G(8), ENUM,  42, 6, 1, 50, 6, 1, 24, 65,   0,   2, st_mmod},
  367.     {FNRM, PEND,   0, 0, 0,  0, 0, 0,  0,  0,   0,   0, NULL}
  368. };
  369.  
  370. /*
  371.  * Fixed part of display
  372.  */
  373. char *st_scrn[] = {
  374. /*
  375.  000000000111111111122222222223333333333444444444455555555556666666666777777
  376.  123456789012345678901234567890123456789012345678901234567890123456789012345
  377. */
  378. "SINGLE Patch     : \"          \" | Src   | Vol     |        | AM     | AM",
  379. " KS  | Vibrato: Depth     | Speed     |    Shape         | AT     | Wheel",
  380. "Curve   | Bend: Depth     | Time      | Vel     | KS     | AT     | Range",
  381. "SOURCES:      Wave     Trkng   Coarse Fine f/KS Bend f/AT",
  382. "   S1",
  383. "   S2",
  384. "   S3",
  385. "   S4",
  386. "Envelope: Lev Del Att Dec Sus Rel Lev/V V/Cur Lev/AT Lev/KS Dur/V Dur/KS",
  387. "   S1",
  388. "   S2",
  389. "   S3",
  390. "   S4",
  391. "------------------------------------------------------------------------",
  392. "MULTIPLE Patch     : \"          \"  | Vol",
  393. "      Source       Levl Tran Tune Out Poly Chan ZnLo ZnHi VSwch Mode",
  394. "S1",
  395. "S2",
  396. "S3",
  397. "S4",
  398. "S5",
  399. "S6",
  400. "S7",
  401. "S8",
  402. NULL
  403. };
  404.  
  405. /*
  406. 000000000111111111122222222223333333333444444444455555555556666666666777777
  407. 123456789012345678901234567890123456789012345678901234567890123456789012345
  408.       Source       Levl Tran Tune Out Poly Chan ZnLo ZnHi VSwch Mode
  409. S1 IA-1 xxxxxxxxxx 100  -24  -50  L+R  VR   1   127  127  Loud  MIDI
  410. */
  411.  
  412. unsigned char dump[64][88];     /* 64 SINGLE patch array */
  413. unsigned char mdump[32][76];    /* 32 MULTIPLE patch array */
  414.  
  415. int curpatch;   /* current SINGLE patch number */
  416. int curmpatch;  /* current MULTIPLE patch number */
  417. int curparam;   /* current SINGLE patch parameter */
  418. int curmparam;  /* current MULTIPLE patch parameter */
  419. int single;     /* true if SINGLE display active; false if MULTIPLE active */
  420. int echo;       /* MIDI echo if true */
  421.  
  422. /*
  423.  * Show fixed part of screen
  424.  */
  425. void
  426. distemplate(screen)
  427. char *screen[];
  428. {
  429.     register int n, i;
  430.     char str[82];
  431.  
  432.     clrscr();
  433.     for (n = 0; st_scrn[n] != NULL; n++)
  434.     {
  435.         (void)strcpy(str, screen[n]);
  436.         for (i = strlen(str); i < 79; i++)
  437.             str[i] = ' ';
  438.         str[i] = '\0';
  439.         gotoxy(1, n+1);
  440.         cprintf("%s", str);
  441.     }
  442. }
  443.  
  444. /*
  445.  * display patch from data at ``dp''
  446.  */
  447. void
  448. dispatch(dp)
  449. unsigned char *dp;
  450. {
  451.     register struct param *pp;
  452.     int cur;
  453.     void showparam();
  454.     void eraseparam();
  455.     void showid();
  456.  
  457.     for (pp = single?params:mparams; pp->p_type != PEND; pp++)
  458.         if (visible(pp, dp))
  459.             showparam(pp, dp);
  460.         else
  461.             eraseparam(pp);
  462.  
  463.     if (single)
  464.     {
  465.         gotoxy(14, 1);
  466.         cur = curpatch;
  467.         pp = ¶ms[curparam];
  468.     }
  469.     else
  470.     {
  471.         gotoxy(16, 15);
  472.         cur = curmpatch;
  473.         pp = &mparams[curmparam];
  474.     }
  475.     showid(cur);
  476.     gotoxy((int)pp->p_col, (int)pp->p_row);
  477. }
  478.  
  479. /*
  480.  * refresh screen
  481.  */
  482. void
  483. refresh()
  484. {
  485.     int snglsv = single;
  486.  
  487.     distemplate();
  488.     single = 1;
  489.     dispatch(&dump[curpatch][0]);
  490.     single = 0;
  491.     dispatch(&mdump[curmpatch][0]);
  492.     single = snglsv;
  493. }
  494.  
  495. char *st_plet[] = {"IA", "IB", "IC", "ID", "iA", "iB", "iC", "iD"};
  496.  
  497. /*
  498.  * returns Kawai patch ID
  499.  */
  500. char *
  501. idstr(n)
  502. int n;
  503. {
  504.     static char tstr[10];
  505.  
  506.     n &= 0x3f;
  507.     (void)sprintf(tstr, "%s-%d", st_plet[n>>3], 1+(n&0x7));
  508.     return tstr;
  509. }
  510.  
  511. /*
  512.  * displays, at current position, Kawai patch ID
  513.  */
  514. void
  515. showid(n)
  516. {
  517.     highvideo();
  518.     cprintf("%s", idstr(n));
  519.     normvideo();
  520. }
  521.  
  522. /*
  523.  * extract the value (integer) of a given parameter, given a pointer
  524.  * of its descriptor and the patch data
  525.  */
  526. int bitmask[] = {0, 1, 3, 7, 15, 31, 63, 127, 255};
  527.  
  528. int
  529. getvalue(pp, dp)
  530. register struct param *pp;
  531. unsigned char *dp;
  532. {
  533.     int val;
  534.  
  535.     val = (dp[pp->p_byte]>>pp->p_bit)&bitmask[pp->p_nbits];
  536.     if (pp->p_secnbits > 0)
  537.         val |= ((dp[pp->p_secbyte]>>pp->p_secbit)
  538.             &bitmask[pp->p_secnbits])<<pp->p_nbits;
  539.     val += pp->p_bias;
  540.     return val;
  541. }
  542.  
  543. /*
  544.  * set the value (integer) of a given parameter, given a pointer
  545.  * of its descriptor, the value, and a pointer to the patch data
  546.  */
  547. void
  548. setvalue(pp, val, dp)
  549. register struct param *pp;
  550. int val;
  551. unsigned char *dp;
  552. {
  553.     int oval;
  554.  
  555.     if (val > pp->p_limit)
  556.         val = pp->p_limit;
  557.     val -= pp->p_bias;
  558.     if (val < 0)
  559.         val = 0;
  560.  
  561.     oval = dp[pp->p_byte]&~(bitmask[pp->p_nbits]<<pp->p_bit);
  562.     dp[pp->p_byte] = oval|((val&bitmask[pp->p_nbits])<<pp->p_bit);
  563.     if (pp->p_secnbits == 0)
  564.         return;
  565.  
  566.     oval = dp[pp->p_secbyte]&~(bitmask[pp->p_secnbits]<<pp->p_secbit);
  567.     dp[pp->p_secbyte] = oval|
  568.          (((val>>pp->p_nbits)&bitmask[pp->p_secnbits])<<pp->p_secbit);
  569.     return;
  570. }
  571.  
  572. void
  573. showparam(pp, dp)
  574. register struct param *pp;
  575. unsigned char *dp;
  576. {
  577.     int val;
  578.     void showval();
  579.     void showstr();
  580.  
  581.     if (pp->p_type == LSTR)
  582.     {
  583.         showval(pp, 0, dp);
  584.         return;
  585.     }
  586.     val = getvalue(pp, dp);
  587.     if (val > pp->p_limit)
  588.         showstr(pp, "#");
  589.     else
  590.         showval(pp, val, dp);
  591. }
  592.  
  593. /*
  594.  * convert the integer value of a parameter to its display form
  595.  */
  596. char *
  597. valstr(pp, val, dp)
  598. register struct param *pp;
  599. int val;
  600. unsigned char *dp;
  601. {
  602.     static char str[40];
  603.  
  604.     switch (pp->p_type)
  605.     {
  606.     case LSTR:
  607.         (void)strncpy(str, (char *)&dp[pp->p_byte], pp->p_limit);
  608.         str[pp->p_limit] = '\0';
  609.         break;
  610.  
  611.     case ENUM:
  612.         (void)strcpy(str, pp->p_names[val]);
  613.         break;
  614.  
  615.     case UNUM:
  616.         (void)sprintf(str, "%d  ", val);
  617.         if (pp->p_limit > 99)
  618.             str[3] = '\0';
  619.         else if (pp->p_limit > 9)
  620.             str[2] = '\0';
  621.         else
  622.             str[1] = '\0';
  623.         break;
  624.  
  625.     case SPL1:
  626.         if ((dp[pp->p_byte+8]&02) == 0)
  627.             (void)sprintf(str, "%s%d  ", st_note[val%12], val/12-4);
  628.         else
  629.         {
  630.             if (val >= 84)
  631.                 (void)sprintf(str, "+%d  ", val-84);
  632.             else
  633.                 (void)sprintf(str, "-%d  ", 84-val);
  634.         }
  635.         str[4] = '\0';
  636.         break;
  637.  
  638.     case SPL2:
  639.         (void)sprintf(str, "%s ", idstr(val));
  640.         (void)strncpy(str+5, (char *)&dump[val][0], 10);
  641.         str[15] = '\0';
  642.         break;
  643.  
  644.     case SPL3:
  645.         (void)sprintf(str, "%s%d  ", st_note[val%12], val/12-2);
  646.         str[4] = '\0';
  647.         break;
  648.  
  649.     case SNUM:
  650.         if (val < 0)
  651.         {
  652.             str[0] = '-';
  653.             val = -val;
  654.         }
  655.         else
  656.             str[0] = '+';
  657.  
  658.         (void)sprintf(str+1, "%d  ", val);
  659.  
  660.         if (pp->p_limit > 99)
  661.             str[4] = '\0';
  662.         else if (pp->p_limit > 9)
  663.             str[3] = '\0';
  664.         else
  665.             str[2] = '\0';
  666.         break;
  667.     }
  668.     return str;
  669. }
  670.  
  671. /*
  672.  * erase the screen area occupied by a given parameter
  673.  */
  674. void
  675. eraseparam(pp)
  676. register struct param *pp;
  677. {
  678.     int n;
  679.     char estr[40];
  680.  
  681.     switch (pp->p_type)
  682.     {
  683.     case LSTR:
  684.         n = pp->p_limit;
  685.         break;
  686.  
  687.     case ENUM:
  688.         n = strlen(pp->p_names[0]);
  689.         break;
  690.  
  691.     case UNUM:
  692.         if (pp->p_limit > 99)
  693.             n = 3;
  694.         else if (pp->p_limit > 9)
  695.             n = 2;
  696.         else
  697.             n = 1;
  698.         break;
  699.  
  700.     case SPL1:
  701.         n = 6;
  702.         break;
  703.  
  704.     case SPL2:
  705.         n = 15;
  706.         break;
  707.  
  708.     case SPL3:
  709.         n = 4;
  710.         break;
  711.  
  712.     case SNUM:
  713.         if (pp->p_limit > 99)
  714.             n = 4;
  715.         else if (pp->p_limit > 9)
  716.             n = 3;
  717.         else
  718.             n = 2;
  719.         break;
  720.     }
  721.     estr[n] = '\0';
  722.     while (--n >= 0)
  723.         estr[n] = ' ';
  724.     gotoxy((int)pp->p_col, (int)pp->p_row);
  725.     cprintf("%s", estr);
  726. }
  727.  
  728. /*
  729.  * given a parameter desc., value, and patch, display at the appropriate
  730.  * screen position
  731.  */
  732. void
  733. showval(pp, val, dp)
  734. struct param *pp;
  735. int val;
  736. unsigned char *dp;
  737. {
  738.     char *valstr();
  739.     void showstr();
  740.  
  741.     showstr(pp, valstr(pp, val, dp));
  742. }
  743.  
  744. /*
  745.  * given a parameter desc. and a string, display the string at the
  746.  * appropriate place on the screen
  747.  */
  748. void
  749. showstr(pp, str)
  750. register struct param *pp;
  751. char *str;
  752. {
  753.  
  754.     gotoxy((int)pp->p_col, (int)pp->p_row);
  755.     highvideo();
  756.     cprintf("%s", str);
  757.     normvideo();
  758. }
  759.  
  760. /*
  761.  * given a parameter desc. and patch, return true of the parameter is
  762.  * visible, and false if it is not
  763.  */
  764. int
  765. visible(pp, dp)
  766. struct param *pp;
  767. unsigned char *dp;
  768. {
  769.     int flags;
  770.  
  771.     flags = pp->p_flags;
  772.     if (single)
  773.     {
  774.         if ((flags&FSC4) != 0 && (dp[11]&0x4) == 0)
  775.             return 0;
  776.         else
  777.             return 1;
  778.     }
  779.     else
  780.     {
  781.         if ((flags&FSGL) != 0 && (dp[34+(flags&0x0f)]&0x0f) == 1)
  782.             return 0;
  783.         else
  784.             return 1;
  785.     }
  786.     /*NOTREACHED*/
  787. }
  788.  
  789.  
  790. /*
  791.  * MIDI routines; calls the following low-level routines defined in io401.c:
  792.  */
  793. extern int getdata();
  794. extern int putdata();
  795. extern int putcmd();
  796.  
  797. #include "mpu401.h"
  798. /*
  799.  * Many routines call tstesc() to see if an abort is requested.  This is
  800.  * useful if the interface hangs, the K-1 doesn't (or can't) answer,
  801.  * and so forth.
  802.  */
  803.  
  804. int is_midiinit = 0;    /* set if MPU401 initialized */
  805.  
  806. /*
  807.  * put the MPU401 into UART mode
  808.  */
  809. void
  810. rawmidi()
  811. {
  812.     void flushmidi();
  813.     void tstesc();
  814.  
  815.     if (is_midiinit)
  816.         return;
  817.     flushmidi();
  818.     while (putcmd(RESET) < 0)
  819.         tstesc();
  820.     while (putcmd(UART) < 0)
  821.         tstesc();
  822.     is_midiinit = 1;
  823. }
  824.  
  825. /*
  826.  * echo any incoming MIDI data
  827.  */
  828. void
  829. midiecho()
  830. {
  831.     int j;
  832.  
  833.     rawmidi();
  834.     while ((j = getdata()) != -1)
  835.         putdata(j);
  836. }
  837.  
  838. /*
  839.  * eat up any incoming MIDI data; echo if that option is on
  840.  */
  841. void
  842. flushmidi()
  843. {
  844.     int j;
  845.  
  846.     while ((j = getdata()) != -1)
  847.     {
  848.         if (echo)
  849.             (void) putdata(j);
  850.         tstesc();
  851.     }
  852. }
  853.  
  854. /*
  855.  * send a MIDI byte; retries and tests for abort
  856.  */
  857. void
  858. sendmidi(x)
  859. int x;
  860. {
  861.     void tstesc();
  862.  
  863.     while (putdata(x) < 0)
  864.         tstesc();
  865. }
  866.  
  867. /*
  868.  * wait for a particular MIDI byte
  869.  */
  870. waitmidi(x)
  871. int x;
  872. {
  873.     int j;
  874.     void tstesc();
  875.  
  876.     while ((j = getdata()) != x)
  877.     {
  878.         if (echo)
  879.             sendmidi(j);
  880.         tstesc();
  881.     }
  882. }
  883.  
  884. /*
  885.  * complains if the next MIDI byte isn't the one given.
  886.  */
  887. void
  888. expectmidi(x)
  889. int x;
  890. {
  891.     int j;
  892.     void errpnt();
  893.  
  894.     if ((j = getdata()) != x)
  895.         errpnt("Got 0x%x, expected 0x%x", j, x, 0);
  896. }
  897.  
  898. /*
  899.  * sound a MIDI note at a given velocity.  velocity 0 turns off.
  900.  */
  901. midinote(n, v)
  902. int n;
  903. int v;
  904. {
  905.     flushmidi();
  906.     sendmidi(0x90);
  907.     sendmidi(n);
  908.     sendmidi(v);
  909. }
  910.  
  911. /*
  912.  * do a MIDI program change to a given program (i.e. patch) number.
  913.  */
  914. midipgm(n)
  915. int n;
  916. {
  917.     flushmidi();
  918.     sendmidi(0xc0);
  919.     sendmidi(n);
  920. }
  921.  
  922. /*
  923.  * get a positive MIDI byte; ignore all others except choke on a
  924.  * (premature) EOX.
  925.  */
  926. int
  927. getposdata()
  928. {
  929.     int j;
  930.     void errpnt();
  931.  
  932.     while ((j = getdata()) > 0x7f)
  933.         if (j == 0xf7)
  934.         {
  935.             errpnt("Unexpected EOX", 0, 0, 0);
  936.         }
  937.     return j;
  938. }
  939.  
  940. /*
  941.  * if there is a character typed at the keyboard, see if it is an ESC.
  942.  * If so, longjmp() to abort the current high-level MIDI routine.
  943.  */
  944. #include <setjmp.h>
  945.  
  946. jmp_buf esccontext;
  947.  
  948. void
  949. tstesc()
  950. {
  951.     void longjmp();
  952.  
  953.     if (kbhit())
  954.         if (getch() == 033)
  955.             longjmp(esccontext, 1);
  956. }
  957.  
  958. /*
  959.  * have K-1 dump all internal patches into our buffers
  960.  */
  961. void
  962. recvdump()
  963. {
  964.     void recvmidi();
  965.     void errpnt();
  966.  
  967.     if (setjmp(esccontext))
  968.     {
  969.         errpnt("MIDI operation aborted", 0, 0, 0);
  970.         return;
  971.     }
  972.     rawmidi();
  973.     recvmidi(0x01, 0x00, 0x00, 88, 32, &dump[0][0]);
  974.     recvmidi(0x01, 0x00, 0x20, 88, 32, &dump[32][0]);
  975.     recvmidi(0x01, 0x00, 0x40, 76, 32, &mdump[0][0]);
  976. }
  977.  
  978. /*
  979.  * dump our buffers into the K-1
  980.  */
  981. void
  982. trandump()
  983. {
  984.     void xmitmidi();
  985.     void errpnt();
  986.  
  987.     if (setjmp(esccontext))
  988.     {
  989.         errpnt("MIDI operation aborted", 0, 0, 0);
  990.         return;
  991.     }
  992.     rawmidi();
  993.     xmitmidi(0x21, 0x00, 0x00, 88, 32, &dump[0][0]);
  994.     xmitmidi(0x21, 0x00, 0x20, 88, 32, &dump[32][0]);
  995.     xmitmidi(0x21, 0x00, 0x40, 76, 32, &mdump[0][0]);
  996. }
  997.  
  998. /*
  999.  * have K-1 dump the current patch
  1000.  */
  1001. void
  1002. recvpatch()
  1003. {
  1004.     if (single)
  1005.         recvmidi(0x00, 0x00, curpatch, 88, 1, &dump[curpatch][0]);
  1006.     else
  1007.         recvmidi(0x00, 0x00, curmpatch+0x40, 76, 1, &mdump[curmpatch][0]);
  1008. }
  1009.  
  1010. /*
  1011.  * dump the current patch into the K-1
  1012.  */
  1013. void
  1014. tranpatch()
  1015. {
  1016.     if (single)
  1017.         xmitmidi(0x20, 0x00, curpatch, 88, 1, &dump[curpatch][0]);
  1018.     else
  1019.         xmitmidi(0x20, 0x00, curmpatch+0x40, 76, 1, &mdump[curmpatch][0]);
  1020. }
  1021.  
  1022. /*
  1023.  * generic K-1 dump receive routine
  1024.  */
  1025. void
  1026. recvmidi(func, sub1, sub2, size, howmany, data)
  1027. int func;
  1028. int sub1;
  1029. int sub2;
  1030. int size;
  1031. int howmany;
  1032. unsigned char *data;
  1033. {
  1034.     int i, n, j;
  1035.     int checksum;
  1036.     void errpnt();
  1037.  
  1038.     flushmidi();
  1039.     sendmidi(0xf0);
  1040.     sendmidi(0x40);
  1041.     sendmidi(0x00);
  1042.     sendmidi(func);
  1043.     sendmidi(0x00);
  1044.     sendmidi(0x03);
  1045.     sendmidi(sub1);
  1046.     sendmidi(sub2);
  1047.     sendmidi(0xf7);
  1048.     waitmidi(0xf0);
  1049.     expectmidi(0x40);
  1050.     expectmidi(0x00);
  1051.     expectmidi(func|0x20);
  1052.     expectmidi(0x00);
  1053.     expectmidi(0x03);
  1054.     expectmidi(sub1);
  1055.     expectmidi(sub2);
  1056.  
  1057.     for (n = 0; n < howmany; n++)
  1058.     {
  1059.         checksum = 0xa5;
  1060.         for (i = 0; i < size-1; i++)
  1061.         {
  1062.             j = getposdata();
  1063.             checksum += j;
  1064.             *data++ = j;
  1065.         }
  1066.         j = getposdata();
  1067.         *data++ = j;
  1068.         if (j != (checksum&0x7f))
  1069.             errpnt("Checksum(%d) %x != %x", n, checksum&0x7f, j);
  1070.     }
  1071.     expectmidi(0xf7);
  1072. }
  1073.  
  1074. /*
  1075.  * generic K-1 dump transmit routine
  1076.  */
  1077. void
  1078. xmitmidi(func, sub1, sub2, size, howmany, data)
  1079. int func;
  1080. int sub1;
  1081. int sub2;
  1082. int size;
  1083. int howmany;
  1084. unsigned char *data;
  1085. {
  1086.     int i, n, j;
  1087.     int checksum;
  1088.     void errpnt();
  1089.  
  1090.     flushmidi();
  1091.     sendmidi(0xf0);
  1092.     sendmidi(0x40);
  1093.     sendmidi(0x00);
  1094.     sendmidi(func);
  1095.     sendmidi(0x00);
  1096.     sendmidi(0x03);
  1097.     sendmidi(sub1);
  1098.     sendmidi(sub2);
  1099.  
  1100.     for (n = 0; n < howmany; n++)
  1101.     {
  1102.         checksum = 0xa5;
  1103.         for (i = 0; i < size-1; i++)
  1104.         {
  1105.             j = *data++;
  1106.             checksum += j;
  1107.             sendmidi(j);
  1108.         }
  1109.         data++;
  1110.         sendmidi(checksum&0x7f);
  1111.         while (getdata() != -1)
  1112.             tstesc();
  1113.     }
  1114.     sendmidi(0xf7);
  1115.  
  1116.     waitmidi(0xf0);
  1117.     expectmidi(0x40);
  1118.     expectmidi(0x00);
  1119.     j = getdata();
  1120.     expectmidi(0x00);
  1121.     expectmidi(0x03);
  1122.     expectmidi(0xf7);
  1123.     if (j != 0x40)
  1124.         errpnt("Write error %d", j-0x40, 0, 0);
  1125. }
  1126.  
  1127. /*
  1128.  * display an error message on the status line
  1129.  */
  1130. void
  1131. errpnt(str, a1, a2, a3)
  1132. char *str;
  1133. {
  1134.     gotoxy(1, 25);
  1135.     cprintf(str, a1, a2, a3);
  1136.     sleep(2);
  1137. }
  1138.  
  1139. /*
  1140.  * save buffers into named file
  1141.  */
  1142. void
  1143. savedump(file)
  1144. char *file;
  1145. {
  1146.     FILE *fp = fopen(file, "wb");
  1147.  
  1148.     if (fp == NULL)
  1149.         errpnt("Can't create file %s", file, 0, 0);
  1150.     else
  1151.     {
  1152.         if (fwrite((char *)&dump[0][0], 88, 64, fp) != 64)
  1153.             errpnt("Trouble writing %s", file, 0, 0);
  1154.         else if (fwrite((char *)&mdump[0][0], 76, 32, fp) != 32)
  1155.             errpnt("Trouble writing %s", file, 0, 0);
  1156.     }
  1157. }
  1158.  
  1159. /*
  1160.  * load buffers from named file
  1161.  */
  1162. void
  1163. loaddump(file)
  1164. char *file;
  1165. {
  1166.     FILE *fp = fopen(file, "rb");
  1167.  
  1168.     if (fp == NULL)
  1169.         errpnt("Can't open file %s", file, 0, 0);
  1170.     else
  1171.     {
  1172.         if (fread((char *)&dump[0][0], 88, 64, fp) != 64)
  1173.             errpnt("Trouble reading %s", file, 0, 0);
  1174.         else if (fread((char *)&mdump[0][0], 76, 32, fp) != 32)
  1175.             errpnt("Trouble reading %s", file, 0, 0);
  1176.     }
  1177. }
  1178.  
  1179. /*
  1180.  * If TurboC's getch() routine returns a 0 first to indicate a special
  1181.  * code, we turn on bit 7 in our representation of the code.
  1182.  */
  1183. #define cHOME 0xc7      /* HOME key code */
  1184. #define cUP   0xc8      /* UP    "   "   */
  1185. #define cPGUP 0xc9      /* PgUP  "   "   */
  1186. #define cLEFT 0xcb      /* LEFT  "   "   */
  1187. #define cRGHT 0xcd      /* RIGHT "   "   */
  1188. #define cEND  0xcf      /* END   "   "   */
  1189. #define cDOWN 0xd0      /* DOWN  "   "   */
  1190. #define cPGDN 0xd1      /* PgDOWN "  "   */
  1191. #define cINS  0xd2      /* INSERT "  "   */
  1192. #define cDEL  0xd3      /* DELETE "  "   */
  1193. #define cF1   0xbb      /* F1    "   "   */
  1194. #define cF8   0xc2      /* F2    "   "   */
  1195. #define cF10  0xc4      /* F10   "   "   */
  1196. #define cFORM 0x0c      /* ^L    "   "   */
  1197.  
  1198. #define INROW 25        /* row used for input prompt */
  1199.  
  1200. /*
  1201.  * Display prompt string and then grab typed value into buffer.
  1202.  * Buffer contents displayed, and may be edited.
  1203.  */
  1204. char *
  1205. getinput(prompt, str)
  1206. char *prompt;
  1207. char *str;
  1208. {
  1209.     int cursor, stcur;
  1210.     int c;
  1211.     int insert;
  1212.  
  1213.     gotoxy(1, INROW);
  1214.     cprintf("%s: %s", prompt, str);
  1215.     stcur = 3+strlen(prompt);
  1216.     cursor = 0;
  1217.     insert = 0;
  1218.     gotoxy(cursor+stcur, INROW);
  1219.     for (;;)
  1220.     {
  1221.         while (kbhit() == 0)
  1222.             if (echo)
  1223.                 midiecho();
  1224.         c = getch();
  1225.         if (c == 0)
  1226.             c = 0x80|getch();
  1227.  
  1228.         switch(c)
  1229.         {
  1230.         case cLEFT:
  1231.             if (cursor > 0)
  1232.                 cursor--;
  1233.             break;
  1234.  
  1235.         case '\b':
  1236.         case '\177':
  1237.             if (cursor > 0)
  1238.             {
  1239.                 cursor--;
  1240.                 gotoxy(cursor+stcur, INROW);
  1241.                 cprintf("%s ", str+cursor+1);
  1242.                 (void)strcpy(str+cursor, str+cursor+1);
  1243.             }
  1244.             else
  1245.             {
  1246.                 str[0] = '\0';
  1247.                 clreol();
  1248.             }
  1249.             break;
  1250.  
  1251.         case cRGHT:
  1252.             if (str[cursor] != '\0')
  1253.                 cursor++;
  1254.             break;
  1255.  
  1256.         case cDEL:
  1257.             if (str[cursor] != '\0')
  1258.             {
  1259.                 gotoxy(cursor+stcur, INROW);
  1260.                 cprintf("%s ", str+cursor+1);
  1261.                 (void)strcpy(str+cursor, str+cursor+1);
  1262.             }
  1263.             break;
  1264.  
  1265.         case cINS:
  1266.             insert = !insert;
  1267.             break;
  1268.  
  1269.         case '\33':
  1270.             gotoxy(1, INROW);
  1271.             clreol();
  1272.             return NULL;
  1273.  
  1274.         case '\n':
  1275.         case '\r':
  1276.             gotoxy(1, INROW);
  1277.             clreol();
  1278.             return str;
  1279.  
  1280.         default:
  1281.             if (c > 0x7f)
  1282.                 break;
  1283.             if (insert)
  1284.             {
  1285.                 char *cp, *op;
  1286.  
  1287.                 for (cp = str+cursor; *cp; cp++)
  1288.                     ;
  1289.                 op = cp;
  1290.                 cp++;
  1291.                 while (op >= str+cursor)
  1292.                     *cp-- = *op--;
  1293.             }
  1294.             if (str[cursor] == '\0')
  1295.                 str[cursor+1] = '\0';
  1296.             str[cursor] = c;
  1297.             cprintf("%s ", str+cursor);
  1298.             cursor++;
  1299.             break;
  1300.         }
  1301.         gotoxy(stcur+cursor, INROW);
  1302.     }
  1303.     /*NOTREACHED*/
  1304. }
  1305.  
  1306. char noteon[8];         /* true if note is currently on */
  1307.  
  1308. /*
  1309.  * Top-level command routine.
  1310.  */
  1311. void
  1312. docommand()
  1313. {
  1314.     int c, cur, size, len, row, col, *curpch, *curprm;
  1315.     char str[80];
  1316.     unsigned char *dp, *altdp;
  1317.     struct param *pp, *altpp, *svpp;
  1318.     void strsetval();
  1319.  
  1320.     if (setjmp(esccontext))
  1321.     {
  1322.         errpnt("MIDI operation aborted", 0, 0, 0);
  1323.         return;
  1324.     }
  1325.     if (single)
  1326.     {
  1327.         dp = &dump[curpatch][0];
  1328.         altdp = &mdump[curmpatch][0];
  1329.         size = 88;
  1330.         curpch = &curpatch;
  1331.         curprm = &curparam;
  1332.         len = 64;
  1333.         pp = ¶ms[curparam];
  1334.         altpp = &mparams[curmparam];
  1335.     }
  1336.     else
  1337.     {
  1338.         altdp = &dump[curpatch][0];
  1339.         dp = &mdump[curmpatch][0];
  1340.         size = 76;
  1341.         curpch = &curmpatch;
  1342.         curprm = &curmparam;
  1343.         len = 32;
  1344.         pp = &mparams[curmparam];
  1345.         altpp = ¶ms[curparam];
  1346.     }
  1347.  
  1348.     while (kbhit() == 0)
  1349.         if (echo)
  1350.             midiecho();
  1351.     c = getch();
  1352.     if (c == 0)
  1353.     {
  1354.         c = 0x80|getch();
  1355.         /* F1 - F8 play tritone-spaced notes at midling velocity */
  1356.         if (is_midiinit && c >= cF1 && c <= cF8)
  1357.         {
  1358.             c -= cF1;
  1359.             if (noteon[c])
  1360.             {
  1361.                 midinote(36+c*6, 0);
  1362.                 noteon[c] = 0;
  1363.             }
  1364.             else
  1365.             {
  1366.                 midinote(36+c*6, 72);
  1367.                 noteon[c] = 1;
  1368.             }
  1369.             return;
  1370.         }
  1371.     }
  1372.     switch (c)
  1373.     {
  1374.         /* Save buffers in file */
  1375.     case 's':
  1376.     case 'S':
  1377.         str[0] = '\0';
  1378.         if (getinput("Save file name", str) != NULL && str[0] != '\0')
  1379.             savedump(str);
  1380.         break;
  1381.  
  1382.         /* Load buffered from file */
  1383.     case 'l':
  1384.     case 'L':
  1385.         str[0] = '\0';
  1386.         if (getinput("Load file name", str) != NULL && str[0] != '\0')
  1387.             loaddump(str);
  1388.         refresh();
  1389.         break;
  1390.  
  1391.         /* receive single patch from K-1 */
  1392.     case 'r':
  1393.         recvpatch();
  1394.         midipgm(single?(*curpch):(*curpch|0x40));
  1395.         refresh();
  1396.         break;
  1397.  
  1398.         /* Receive all patches from of K-1 */
  1399.     case 'R':
  1400.         recvdump();
  1401.         midipgm(single?(*curpch):(*curpch|0x40));
  1402.         refresh();
  1403.         break;
  1404.  
  1405.         /* transmit single patch to K-1 */
  1406.     case 't':
  1407.         tranpatch();
  1408.         midipgm(single?(*curpch):(*curpch|0x40));
  1409.         break;
  1410.  
  1411.         /* Transmit all patches to K-1 */
  1412.     case 'T':
  1413.         trandump();
  1414.         midipgm(single?(*curpch):(*curpch|0x40));
  1415.         break;
  1416.  
  1417.         /* Quit patch editor */
  1418.     case 'q':
  1419.     case 'Q':
  1420.         (void)strcpy(str, "Yes");
  1421.         if (getinput("Confirm (Y/N)", str) != NULL && (str[0]|0x20) == 'y')
  1422.         {
  1423.             gotoxy(1, 25);
  1424.             exit(0);
  1425.         }
  1426.         break;
  1427.  
  1428.         /* toggle MIDI echo */
  1429.     case 'e':
  1430.         echo = !echo;
  1431.         break;
  1432.  
  1433.         /* switch between SINGLE and MULTI */
  1434.     case cF10:
  1435.         single = !single;
  1436.         dp = altdp;
  1437.         pp = altpp;
  1438.         dispatch(dp);
  1439.         if (is_midiinit)
  1440.             midipgm(single?(*curpch):(*curpch|0x40));
  1441.         break;
  1442.  
  1443.         /* refresh screen */
  1444.     case cFORM:
  1445.         refresh();
  1446.         break;
  1447.  
  1448.         /* show previous patch */
  1449.     case cPGUP:
  1450.         if (*curpch > 0)
  1451.         {
  1452.             (*curpch)--;
  1453.             dp -= size;
  1454.         }
  1455.         dispatch(dp);
  1456.         if (!visible(pp, dp))
  1457.         {
  1458.             pp -= *curprm;
  1459.             *curprm = 0;
  1460.         }
  1461.         if (is_midiinit)
  1462.             midipgm(single?(*curpch):(*curpch|0x40));
  1463.         break;
  1464.  
  1465.         /* show next patch */
  1466.     case cPGDN:
  1467.         if (*curpch < len-1)
  1468.         {
  1469.             (*curpch)++;
  1470.             dp += size;
  1471.         }
  1472.         dispatch(dp);
  1473.         if (!visible(pp, dp))
  1474.         {
  1475.             pp -= *curprm;
  1476.             *curprm = 0;
  1477.         }
  1478.         if (is_midiinit)
  1479.             midipgm(single?(*curpch):(*curpch|0x40));
  1480.         break;
  1481.  
  1482.         /* move to previous parameter */
  1483.     case cLEFT:
  1484.         do
  1485.         {
  1486.             if (*curprm > 0)
  1487.             {
  1488.                 (*curprm)--;
  1489.                 pp--;
  1490.             }
  1491.             else
  1492.                 break;
  1493.         } while (!visible(pp, dp));
  1494.         break;
  1495.  
  1496.         /* move to next parameter */
  1497.     case cRGHT:
  1498.         do
  1499.         {
  1500.             if ((pp+1)->p_type != PEND)
  1501.             {
  1502.                 (*curprm)++;
  1503.                 pp++;
  1504.             }
  1505.             else
  1506.             {       pp -= *curprm;
  1507.                 *curprm = 0;
  1508.             }
  1509.         } while (!visible(pp, dp));
  1510.         break;
  1511.  
  1512.         /* move up one row */
  1513.     case cUP:
  1514.         row = pp->p_row;
  1515.         col = pp->p_col;
  1516.         do
  1517.         {
  1518.             if (*curprm > 0)
  1519.             {
  1520.                 (*curprm)--;
  1521.                 pp--;
  1522.             }
  1523.             else
  1524.                 break;
  1525.         } while (pp->p_row >= row
  1526.             || pp->p_col > col+3 || !visible(pp, dp));
  1527.         break;
  1528.  
  1529.         /* move down one row */
  1530.     case cDOWN:
  1531.         row = pp->p_row;
  1532.         col = pp->p_col;
  1533.         cur = *curprm;
  1534.         svpp = pp;
  1535.         do
  1536.         {
  1537.             if ((pp+1)->p_type != PEND)
  1538.             {
  1539.                 (*curprm)++;
  1540.                 pp++;
  1541.             }
  1542.             else
  1543.             {
  1544.                 *curprm = cur;
  1545.                 pp = svpp;
  1546.                 break;
  1547.             }
  1548.         } while (pp->p_row <= row
  1549.             || pp->p_col < col-3 || !visible(pp, dp));
  1550.         break;
  1551.  
  1552.         /* move to first parameter */
  1553.     case cHOME:
  1554.         pp -= *curprm;
  1555.         *curprm = 0;
  1556.         break;
  1557.  
  1558.         /* move to last parameter */
  1559.     case cEND:
  1560.         svpp = pp;
  1561.         cur = *curprm;
  1562.  
  1563.         while ((pp+1)->p_type != PEND)
  1564.         {
  1565.             curparam++;
  1566.             pp++;
  1567.             if (visible(pp, dp))
  1568.             {
  1569.                 svpp = pp;
  1570.                 cur = *curprm;
  1571.             }
  1572.         }
  1573.         pp = svpp;
  1574.         *curprm = cur;
  1575.         break;
  1576.  
  1577.         /* add one to parameter value */
  1578.     case '+':
  1579.         if (pp->p_type == LSTR)
  1580.             break;
  1581.         setvalue(pp, getvalue(pp, dp)+1, dp);
  1582.         if (pp->p_flags&FRDW)
  1583.             dispatch(dp);
  1584.         break;
  1585.  
  1586.         /* subtract one from parameter value */
  1587.     case '-':
  1588.         if (pp->p_type == LSTR)
  1589.             break;
  1590.         setvalue(pp, getvalue(pp, dp)-1, dp);
  1591.         if (pp->p_flags&FRDW)
  1592.             dispatch(dp);
  1593.         break;
  1594.  
  1595.         /* allow typein of parameter value */
  1596.     case '\n':
  1597.     case '\r':
  1598.         (void)strcpy(str, valstr(pp, getvalue(pp, dp), dp));
  1599.         if (getinput("Enter value", str) == NULL || str[0] == '\0')
  1600.             break;
  1601.         strsetval(pp, str, dp);
  1602.         if (pp->p_flags&FRDW)
  1603.             dispatch(dp);
  1604.         break;
  1605.  
  1606.         /* ignore other keystrokes */
  1607.     default:
  1608.         break;
  1609.     }
  1610.     if (visible(pp, dp))
  1611.         showparam(pp, dp);
  1612.     gotoxy((int)pp->p_col, (int)pp->p_row);
  1613. }
  1614.  
  1615. /*
  1616.  * set a parameter from a string
  1617.  */
  1618. void
  1619. strsetval(pp, str, dp)
  1620. struct param *pp;
  1621. char *str;
  1622. unsigned char *dp;
  1623. {
  1624.     char **cpp;
  1625.     char tmp[80];
  1626.     int len, val;
  1627.     int match();
  1628.     int notecv();
  1629.  
  1630.     val = -9999;
  1631.     switch(pp->p_type)
  1632.     {
  1633.     case LSTR:
  1634.         (void)strcpy(tmp, str);
  1635.         len = strlen(tmp);
  1636.         while (len < pp->p_limit)
  1637.             tmp[len++] = ' ';
  1638.         (void)strncpy((char *)&dp[pp->p_byte], tmp, pp->p_limit);
  1639.         return;
  1640.  
  1641.     case SNUM:
  1642.     case UNUM:
  1643.         val = atoi(str);
  1644.         break;
  1645.     case ENUM:
  1646.         val = getvalue(pp, dp);
  1647.         for (cpp = pp->p_names; *cpp != NULL; cpp++)
  1648.             if (match(str, *cpp))
  1649.             {
  1650.                 val = (cpp-pp->p_names)+pp->p_bias;
  1651.                 break;
  1652.             }
  1653.         break;
  1654.     case SPL1:
  1655.         if ((dp[pp->p_byte+8]&02) != 0)
  1656.             val = atoi(str);
  1657.         else
  1658.         {
  1659.             val = notecv(str);
  1660.             if (val == -99)
  1661.                 return;
  1662.             val += 24;
  1663.         }
  1664.         break;
  1665.     case SPL3:
  1666.         val = notecv(str);
  1667.         if (val == -99)
  1668.             return;
  1669.         break;
  1670.     }
  1671.     setvalue(pp, val, dp);
  1672. }
  1673.  
  1674. /*
  1675.  * convert string into MIDI note value
  1676.  */
  1677. unsigned char notval[] = {9, 11, 0, 2, 4, 5, 7};
  1678.  
  1679. int
  1680. notecv(str)
  1681. char *str;
  1682. {
  1683.     int val, c;
  1684.  
  1685.     c = (int)(str[0]&~0x20)-'A';
  1686.     if (c < 0 || c > 6)
  1687.         return -99;
  1688.     val = notval[c];
  1689.     c = 1;
  1690.     if (str[1] == '#')
  1691.     {
  1692.         val++;
  1693.         c++;
  1694.     }
  1695.     if (str[c] != '-' && (str[c] < '0' || str[c] > '9'))
  1696.         return -99;
  1697.     else
  1698.         return val+12*(atoi(str+c)+2);
  1699. }
  1700.  
  1701. /*
  1702.  * oddball string match; match on first two characters unless digits,
  1703.  * then look at up to 3.  This allows type-in of waveform numbers,
  1704.  * while two characters are unambiguous for the other stuff.
  1705.  *
  1706.  * Ignore case in the simplest way possible, and ignore the possible
  1707.  * synonyms this creates for other chars.
  1708.  */
  1709. int
  1710. match(r, t)
  1711. char *r, *t;
  1712. {
  1713.     while (*r == ' ')
  1714.         r++;
  1715.     while (*t == ' ')
  1716.         t++;
  1717.     if ((*r++&0x3f) != (*t++&0x3f))
  1718.         return 0;
  1719.     if ((*r++&0x3f) != (*t++&0x3f))
  1720.         return 0;
  1721.     if (*r < '0' || *r > '9')
  1722.         return 1;
  1723.     return (*r == *t);
  1724. }
  1725.  
  1726. /*
  1727.  * Main program -- at end, and I don't even *like* PASCAL...
  1728.  */
  1729. void
  1730. main(argc, argv)
  1731. int argc;
  1732. char **argv;
  1733. /*ARGSUSED*/
  1734. {
  1735.     textmode(7);
  1736.     window(1, 1, 80, 25);
  1737.     /*
  1738.      * Note: you may remove the next two lines for your personal
  1739.      * use but you must replace them before distributing any copies
  1740.      * of this software.
  1741.      */
  1742.     distemplate(st_copyright);
  1743.     sleep(5);
  1744.  
  1745.     distemplate(st_screen);
  1746.     curpatch = 0;
  1747.     curparam = 0;
  1748.     curmpatch = 0;
  1749.     curmparam = 0;
  1750.     echo = 0;
  1751.     single = 0;
  1752.     dispatch(&mdump[curmpatch][0]);
  1753.     single = 1;
  1754.     dispatch(&dump[curpatch][0]);
  1755.     showparam(¶ms[curparam], &dump[curpatch][0]);
  1756.     for (;;)
  1757.         docommand();
  1758.     /*NOTREACHED*/
  1759. }
  1760.