Advertisement
MegaLoler

Sound Chip Tracker

May 6th, 2013
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Feature complete!
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <time.h>
  7. #include <ncurses.h>
  8.  
  9. #define NOTE_NULL 0x0
  10. #define NOTE_RESET 0x1
  11. #define NOTE_ON 0x2
  12. #define NOTE_OFF 0x3
  13. #define NOTE_C 0x4
  14. #define NOTE_Cs 0x5
  15. #define NOTE_Db 0x5
  16. #define NOTE_D 0x6
  17. #define NOTE_Ds 0x7
  18. #define NOTE_Eb 0x7
  19. #define NOTE_E 0x8
  20. #define NOTE_F 0x9
  21. #define NOTE_Fs 0xA
  22. #define NOTE_Gb 0xA
  23. #define NOTE_G 0xB
  24. #define NOTE_Gs 0xC
  25. #define NOTE_Ab 0xC
  26. #define NOTE_A 0xD
  27. #define NOTE_As 0xE
  28. #define NOTE_Bb 0xE
  29. #define NOTE_B 0xF
  30.  
  31. #define EFF_ARPEGGIO 0x0
  32. #define EFF_PITCH_SLIDE_UP 0x1
  33. #define EFF_PITCH_SLIDE_DOWN 0x2
  34. #define EFF_PORTAMENTO 0x3
  35. #define EFF_VIBRATO 0x4
  36. #define EFF_WAVEFORM 0x5
  37. #define EFF_DUTY_CYCLE 0x6
  38. #define EFF_TREMOLO 0x7
  39. #define EFF_PWM 0x8
  40. #define EFF_PITCH 0x9
  41. #define EFF_VOLUME_SLIDE_UP 0xA
  42. #define EFF_VOLUME_SLIDE_DOWN 0xB
  43. #define EFF_VOLUME 0xC
  44. #define EFF_ENVELOPE_ATTACK_DECAY 0xD
  45. #define EFF_ENVELOPE_SUSTAIN_RELEASE 0xE
  46. #define EFF_FINE_TUNE 0xF
  47.  
  48. FILE *out;
  49. char serialPort[255];
  50.  
  51. typedef struct
  52. {
  53.     unsigned char enable;
  54.     unsigned char effect;
  55.     unsigned char argument;
  56.    
  57. } Effect;
  58.  
  59. typedef struct
  60. {
  61.     unsigned char note;
  62.     unsigned char octave;
  63.     unsigned char volume;
  64.     unsigned char applyInstrument;
  65.     unsigned char instrument;
  66.    
  67. } NoteCommand;
  68.  
  69. typedef struct
  70. {
  71.     NoteCommand noteCommand;
  72.     Effect effect;
  73.    
  74. } Entry;
  75.  
  76. typedef struct
  77. {
  78.     Entry entries[4];
  79.    
  80. } Frame;
  81.  
  82. typedef struct
  83. {
  84.     Effect effects[8];
  85.    
  86. } Instrument;
  87.  
  88. typedef struct
  89. {
  90.     Frame frames[32];
  91.    
  92. } Order;
  93.  
  94. typedef struct
  95. {
  96.     unsigned char fps;
  97.     unsigned char orderCount;
  98.     unsigned char repeat;
  99.     unsigned char instrumentCount;
  100.     Instrument *instruments;
  101.     Order *orders;
  102.    
  103. } Song;
  104.  
  105. Song song;
  106.  
  107. void printTabs(int tabs)
  108. {
  109.     int i;
  110.     for(i = 0; i < tabs; i++)
  111.     {
  112.         printf("\t");
  113.     }
  114. }
  115.  
  116. void printEffect(Effect *effect, int tabs)
  117. {
  118.     int s1, s2;
  119.     s1 = (effect->argument) >> 4;
  120.     s2 = (effect->argument) & 0x0F;
  121.     printTabs(tabs);
  122.     if(effect->enable)
  123.     {
  124.         switch(effect->effect)
  125.         {
  126.             case 0x0:
  127.                 if(s1 || s2)
  128.                 {
  129.                     printf("Arpeggio: Semitones: %i, %i\n", s1, s2);
  130.                 }
  131.                 else
  132.                 {
  133.                     printf("Arpeggio Off\n");
  134.                 }
  135.                 break;
  136.             case 0x1:
  137.                 printf("Pitch Slide Up: Rate: %i\n", effect->argument);
  138.                 break;
  139.             case 0x2:
  140.                 printf("Pitch Slide Down: Rate: %i\n", effect->argument);
  141.                 break;
  142.             case 0x3:
  143.                 if(effect->argument)
  144.                 {
  145.                     printf("Portamento: Rate: %i\n", effect->argument);
  146.                 }
  147.                 else
  148.                 {
  149.                     printf("Portamento Off");
  150.                 }
  151.                 break;
  152.             case 0x4:
  153.                 printf("Vibrato: Rate: %i, Depth: %i\n", s1, s2);
  154.                 break;
  155.             case 0x5:
  156.                 printf("Waveform: ");
  157.                 switch(effect->argument)
  158.                 {
  159.                     case 0:
  160.                         printf("Pulse\n");
  161.                         break;
  162.                     case 1:
  163.                         printf("Triangle\n");
  164.                         break;
  165.                     case 2:
  166.                         printf("Sawtooth\n");
  167.                         break;
  168.                     case 3:
  169.                         printf("Noise\n");
  170.                         break;
  171.                     default:
  172.                         printf("Unknown\n");
  173.                 }
  174.                 break;
  175.             case 0x6:
  176.                 printf("Duty Cycle: %i\%\n", effect->argument / 256 * 100);
  177.                 break;
  178.             case 0x7:
  179.                 printf("Tremolo: Rate: %i, Depth: %i\n", s1, s2);
  180.                 break;
  181.             case 0x8:
  182.                 printf("Pulse Width Modulation: Rate: %i, Depth: %i\n", s1, s2);
  183.                 break;
  184.             case 0x9:
  185.                 printf("Pitch: %i\n", effect->argument);
  186.                 break;
  187.             case 0xA:
  188.                 printf("Volume Slide Up: Rate: %i\n", effect->argument);
  189.                 break;
  190.             case 0xB:
  191.                 printf("Volume Slide Down: Rate: %i\n", effect->argument);
  192.                 break;
  193.             case 0xC:
  194.                 printf("Volume: %i\n", effect->argument);
  195.                 break;
  196.             case 0xD:
  197.                 printf("Envelope: Attack: %i, Decay: %i\n", s1, s2);
  198.                 break;
  199.             case 0xE:
  200.                 printf("Envelope: Sustain: %i\%, Release: %i\n", s1 / 16 * 100, s2);
  201.                 break;
  202.             case 0xF:
  203.                 printf("Fine Tune: %i\n", effect->argument);
  204.                 break;
  205.             default:
  206.                 printf("Unknown Effect\n");
  207.         }
  208.     }
  209.     else
  210.     {
  211.         printf("No Effect\n");
  212.     }
  213. }
  214.  
  215. void printInstrumentInfo(Instrument *instrument, int tabs)
  216. {
  217.     int i;
  218.     for(i = 0; i < sizeof(instrument->effects) / sizeof(Effect); i++)
  219.     {
  220.         printTabs(tabs);
  221.         printf("Effect #%i:\n", i + 1);
  222.         printEffect(&(instrument->effects[i]), tabs + 1);
  223.     }
  224. }
  225.  
  226. void printNote(unsigned char note, unsigned char octave, int tabs)
  227. {
  228.     printTabs(tabs);
  229.     switch(note)
  230.     {
  231.         case 0x0:
  232.             printf("No Note\n");
  233.             break;
  234.         case 0x1:
  235.             printf("Reset Oscillator Timer\n");
  236.             break;
  237.         case 0x2:
  238.             printf("Enable Oscillator\n");
  239.             break;
  240.         case 0x3:
  241.             printf("Disable Oscillator\n");
  242.             break;
  243.         case 0x4:
  244.             printf("Play Note C%i\n", octave);
  245.             break;
  246.         case 0x5:
  247.             printf("Play Note C#%i\n", octave);
  248.             break;
  249.         case 0x6:
  250.             printf("Play Note D%i\n", octave);
  251.             break;
  252.         case 0x7:
  253.             printf("Play Note D#%i\n", octave);
  254.             break;
  255.         case 0x8:
  256.             printf("Play Note E%i\n", octave);
  257.             break;
  258.         case 0x9:
  259.             printf("Play Note F%i\n", octave);
  260.             break;
  261.         case 0xA:
  262.             printf("Play Note F#%i\n", octave);
  263.             break;
  264.         case 0xB:
  265.             printf("Play Note G%i\n", octave);
  266.             break;
  267.         case 0xC:
  268.             printf("Play Note G#%i\n", octave);
  269.             break;
  270.         case 0xD:
  271.             printf("Play Note A%i\n", octave);
  272.             break;
  273.         case 0xE:
  274.             printf("Play Note A#%i\n", octave);
  275.             break;
  276.         case 0xF:
  277.             printf("Play Note B%i\n", octave);
  278.             break;
  279.         default:
  280.             printf("Unknown Command\n");
  281.     }
  282. }
  283.  
  284. void printVolume(unsigned char volume, int tabs)
  285. {
  286.     printTabs(tabs);
  287.     if(volume)
  288.     {
  289.         printf("Volume: %i\%\n", volume / 32 * 100);
  290.     }
  291.     else
  292.     {
  293.         printf("Ignore Volume\n");
  294.     }
  295. }
  296.  
  297. void printInstrumentID(unsigned char applyInstrument, unsigned char instrument, int tabs)
  298. {
  299.     printTabs(tabs);
  300.     if(applyInstrument)
  301.     {
  302.         printf("Apply Instrument #%i\n", instrument + 1);
  303.     }
  304.     else
  305.     {
  306.         printf("Ignore Instrument\n");
  307.     }
  308. }
  309.  
  310. void printNoteCommand(NoteCommand *noteCommand, int tabs)
  311. {
  312.     printNote(noteCommand->note, noteCommand->octave, tabs);
  313.     printVolume(noteCommand->volume, tabs);
  314.     printInstrumentID(noteCommand->applyInstrument, noteCommand->instrument, tabs);
  315. }
  316.  
  317. void printEntry(Entry *entry, int tabs)
  318. {
  319.     printNoteCommand(&(entry->noteCommand), tabs);
  320.     printEffect(&(entry->effect), tabs);
  321. }
  322.  
  323. void printFrame(Frame *frame, int tabs)
  324. {
  325.     int i;
  326.     for(i = 0; i < sizeof(frame->entries) / sizeof(Entry); i++)
  327.     {
  328.         printTabs(tabs);
  329.         printf("Channel #%i:\n", i + 1);
  330.         printEntry(&(frame->entries[i]), tabs + 1);
  331.     }
  332. }
  333.  
  334. void printOrderInfo(Order *order, int tabs)
  335. {
  336.     int i;
  337.     for(i = 0; i < sizeof(order->frames) / sizeof(Frame); i++)
  338.     {
  339.         printTabs(tabs);
  340.         printf("Frame #%i:\n", i + 1);
  341.         printFrame(&(order->frames[i]), tabs + 1);
  342.     }
  343. }
  344.  
  345. void printSongInfo(Song *song)
  346. {
  347.     printf("Speed: %i FPS\n", song->fps);
  348.     printf("Length: %i Orders\n", song->orderCount);
  349.     printf("Repeat: Order #%i\n", song->repeat + 1);
  350.     printf("Instrument Count: %i\n", song->instrumentCount);
  351.    
  352.     printf("Instruments:\n");
  353.     int i;
  354.     for(i = 0; i <  song->instrumentCount; i++)
  355.     {
  356.         printf("\tInstrument #%i:\n", i + 1);
  357.         printInstrumentInfo(&(song->instruments[0]), 2);
  358.     }
  359.    
  360.     printf("Orders:\n");
  361.     for(i = 0; i <  song->orderCount; i++)
  362.     {
  363.         printf("\tOrder #%i:\n", i + 1);
  364.         printOrderInfo(&(song->orders[0]), 2);
  365.     }
  366. }
  367.  
  368. void playNote(unsigned char note, unsigned char octave, unsigned char volume, unsigned char osc)
  369. {
  370.     note &= 0x0F;
  371.     octave &= 0b00000111;
  372.     volume &= 0b00011110; // weird bug causing the last bit to make the octave go really high
  373.     osc &= 0b00000011;
  374.    
  375.     char highByte = (octave >> 1) | (volume << 2) | (1 << 7);
  376.     char lowByte = (osc << 1) | (note << 3) | (octave << 7);
  377.    
  378.     fputc(highByte, out);
  379.     fputc(lowByte, out);
  380.     fputc(0xFF, out);
  381.    
  382.     fclose(out);
  383.     out = fopen(serialPort, "w");
  384. }
  385.  
  386. void playEffect(unsigned char effect, unsigned char argument, unsigned char osc)
  387. {
  388.     effect &= 0x0F;
  389.     osc &= 0b00000011;
  390.    
  391.     char highByte = (argument >> 1) | (1 << 7);
  392.     char lowByte = 1 | (osc << 1) | (effect << 3) | (argument << 7);
  393.    
  394.     fputc(highByte, out);
  395.     fputc(lowByte, out);
  396.     fputc(0xFF, out);
  397.    
  398.     fclose(out);
  399.     out = fopen(serialPort, "w");
  400. }
  401.  
  402. void sendEffectCommand(Effect *effect, unsigned char osc)
  403. {
  404.     if(effect->enable)
  405.     {
  406.         playEffect(effect->effect, effect->argument, osc);
  407.     }
  408. }
  409.  
  410. void sendNoteCommand(NoteCommand *noteCommand, unsigned char osc)
  411. {
  412.     if(noteCommand->note || noteCommand->octave || noteCommand->volume)
  413.     {
  414.         if(noteCommand->applyInstrument)
  415.         {
  416.             int i;
  417.             for(i = 0; i < 8; i++)
  418.             {
  419.                 Effect effect = song.instruments[noteCommand->instrument].effects[i];
  420.                 sendEffectCommand(&effect, osc);
  421.             }
  422.         }
  423.         playNote(noteCommand->note, noteCommand->octave, noteCommand->volume, osc);
  424.     }
  425. }
  426.  
  427. void playEntry(Entry *entry, unsigned char osc)
  428. {
  429.     sendEffectCommand(&entry->effect, osc);
  430.     sendNoteCommand(&entry->noteCommand, osc);
  431. }
  432.  
  433. void playFrame(Frame *frame)
  434. {
  435.     playEntry(&frame->entries[0], 0);
  436.     playEntry(&frame->entries[1], 1);
  437.     playEntry(&frame->entries[2], 2);
  438.     playEntry(&frame->entries[3], 3);
  439. }
  440.  
  441. NoteCommand newNoteCommand(unsigned char note, unsigned char octave, unsigned char volume, unsigned char applyInstrument, unsigned char instrument)
  442. {
  443.     NoteCommand command;
  444.     command.note = note;
  445.     command.octave = octave;
  446.     command.volume = volume;
  447.     command.applyInstrument = applyInstrument;
  448.     command.instrument = instrument;
  449.     return command;
  450. }
  451.  
  452. NoteCommand newSimpleNoteCommand(unsigned char note, unsigned char octave, unsigned char volume)
  453. {
  454.     return newNoteCommand(note, octave, volume, 0, 0);
  455. }
  456.  
  457. NoteCommand newSimplestNoteCommand(unsigned char note, unsigned char octave)
  458. {
  459.     return newSimpleNoteCommand(note, octave, 0);
  460. }
  461.  
  462. NoteCommand newNullNoteCommand()
  463. {
  464.     return newSimplestNoteCommand(NOTE_NULL, 0);
  465. }
  466.  
  467. NoteCommand newResetNoteCommand()
  468. {
  469.     return newSimplestNoteCommand(NOTE_RESET, 0);
  470. }
  471.  
  472. NoteCommand newNoteOnCommand()
  473. {
  474.     return newSimplestNoteCommand(NOTE_ON, 0);
  475. }
  476.  
  477. NoteCommand newNoteOffCommand()
  478. {
  479.     return newSimplestNoteCommand(NOTE_OFF, 0);
  480. }
  481.  
  482. Effect newEffect(unsigned char effect, unsigned char argument)
  483. {
  484.     Effect new_effect;
  485.     new_effect.enable = 1;
  486.     new_effect.effect = effect;
  487.     new_effect.argument = argument;
  488.     return new_effect;
  489. }
  490.  
  491. Effect newNullEffect()
  492. {
  493.     Effect effect;
  494.     effect.enable = 0;
  495.     effect.effect = 0;
  496.     effect.argument = 0;
  497.     return effect;
  498. }
  499.  
  500. Entry newEntry(NoteCommand command, Effect effect)
  501. {
  502.     Entry entry;
  503.     entry.noteCommand = command;
  504.     entry.effect = effect;
  505.     return entry;
  506. }
  507.  
  508. Entry newSimpleEntry(NoteCommand command)
  509. {
  510.     return newEntry(command, newNullEffect());
  511. }
  512.  
  513. Entry newNullEntry()
  514. {
  515.     return newEntry(newNullNoteCommand(), newNullEffect());
  516. }
  517.  
  518. Frame newFrame(Entry entry1, Entry entry2, Entry entry3, Entry entry4)
  519. {
  520.     Frame frame;
  521.     frame.entries[0] = entry1;
  522.     frame.entries[1] = entry2;
  523.     frame.entries[2] = entry3;
  524.     frame.entries[3] = entry4;
  525.     return frame;
  526. }
  527.  
  528. Frame newUnisonFrame(Entry entry)
  529. {
  530.     return newFrame(entry, entry, entry, entry);
  531. }
  532.  
  533. Frame newQuietFrame()
  534. {
  535.     return newUnisonFrame(newSimpleEntry(newNoteOffCommand()));
  536. }
  537.  
  538. Order *newEmptyOrder()
  539. {
  540.     Order *order;
  541.    
  542.     int i;
  543.     for(i = 0; i < sizeof(order->frames) / sizeof(Frame); i++)
  544.     {
  545.         order->frames[i] = newQuietFrame();
  546.     }
  547.    
  548.     return order;
  549. }
  550.  
  551. WINDOW *orderWindow;
  552. WINDOW *instrumentWindow;
  553. WINDOW *effectWindow;
  554. WINDOW *trackerWindow;
  555.  
  556. int w1, w2, h1, h2;
  557.  
  558. #define WIN_ORDER 0
  559. #define WIN_INSTR 1
  560. #define WIN_EFFECT 2
  561. #define WIN_TRACKER 3
  562. int curWindow = WIN_TRACKER;
  563.  
  564. #define MODE_EDIT 0
  565. #define MODE_PLAY 1
  566. #define MODE_JAM 2
  567. int curMode = MODE_EDIT;
  568.  
  569. #define MAX_ORDERS 64
  570. #define MAX_INSTRUMENTS 16
  571.  
  572. int curOrder = 0;
  573. int curInstrument = 0;
  574. int curEffect = 0;
  575. int orderScroll = 0;
  576. int instrumentScroll = 0;
  577.  
  578. int curOsc = 0;
  579. int curFrame = 0;
  580. int curCol = 0;
  581. int trackerScroll = 0;
  582.  
  583. int curOctave = 4;
  584.  
  585. void placeCursor()
  586. {
  587.     move(LINES - 1, COLS - 1);
  588. }
  589.  
  590. void printTitle(WINDOW *window, char *title)
  591. {
  592.     int h, w;
  593.     getmaxyx(window, h, w);
  594.     wattron(window, A_BOLD);
  595.     mvwprintw(window, 0,( w - strlen(title)) / 2, "%s", title);
  596. }
  597.  
  598. void drawOrderWindow()
  599. {
  600.     wclear(orderWindow);
  601.     wattrset(orderWindow, A_NORMAL);
  602.     if(curWindow == WIN_ORDER && curMode == MODE_EDIT) wattrset(orderWindow, A_REVERSE);
  603.     box(orderWindow, 0, 0);
  604.     char t[20];
  605.     sprintf(t, "Orders (%i)", song.orderCount);
  606.     printTitle(orderWindow, t);
  607.     wattrset(orderWindow, A_NORMAL);
  608.    
  609.     int i;
  610.     int a;
  611.     for(i = orderScroll; i < song.orderCount && i < h1 - 2 + orderScroll; i++)
  612.     {
  613.         wattrset(orderWindow, curOrder == i ? A_REVERSE : A_NORMAL);
  614.         for(a = 0; a < w1 - 2; a++)
  615.         {
  616.             mvwprintw(orderWindow, i + 1 - orderScroll, a + 1, " ");
  617.         }
  618.         mvwprintw(orderWindow, i + 1 - orderScroll, 1, "%c 0x%x: ", song.repeat == i ? '*' : ' ', i);
  619.     }
  620.    
  621.     wrefresh(orderWindow);
  622.     placeCursor();
  623. }
  624.  
  625. void drawInstrumentWindow()
  626. {
  627.     wclear(instrumentWindow);
  628.     wattrset(instrumentWindow, A_NORMAL);
  629.     if(curWindow == WIN_INSTR && curMode == MODE_EDIT) wattrset(instrumentWindow, A_REVERSE);
  630.     box(instrumentWindow, 0, 0);
  631.     char t[20];
  632.     sprintf(t, "Instruments (%i)", song.instrumentCount);
  633.     printTitle(instrumentWindow, t);
  634.     wattrset(instrumentWindow, A_NORMAL);
  635.    
  636.     int i;
  637.     int a;
  638.     for(i = instrumentScroll; i < song.instrumentCount && i < h1 - 2 + instrumentScroll; i++)
  639.     {
  640.         wattrset(instrumentWindow, curInstrument == i ? A_REVERSE : A_NORMAL);
  641.         for(a = 0; a < w1 - 2; a++)
  642.         {
  643.             mvwprintw(instrumentWindow, i + 1 - instrumentScroll, a + 1, " ");
  644.         }
  645.         mvwprintw(instrumentWindow, i + 1 - instrumentScroll, 1, "0x%x: ", i);
  646.     }
  647.    
  648.     wrefresh(instrumentWindow);
  649.     placeCursor();
  650. }
  651.  
  652. void drawEffectWindow()
  653. {
  654.     wclear(effectWindow);
  655.     wattrset(effectWindow, A_NORMAL);
  656.     if(curWindow == WIN_EFFECT && curMode == MODE_EDIT) wattrset(effectWindow, A_REVERSE);
  657.     box(effectWindow, 0, 0);
  658.     printTitle(effectWindow, "Effects");
  659.     wattrset(effectWindow, A_NORMAL);
  660.    
  661.     Instrument *instrument = &song.instruments[curInstrument];
  662.    
  663.     int i;
  664.     int a;
  665.     for(i = 0; i < sizeof(instrument->effects) / sizeof(Effect); i++)
  666.     {
  667.         Effect effect = instrument->effects[i];
  668.         wattrset(effectWindow, curEffect == i ? A_REVERSE : A_NORMAL);
  669.         for(a = 0; a < w1 - 2; a++)
  670.         {
  671.             mvwprintw(effectWindow, i + 1, a + 1, " ");
  672.         }
  673.         if(!effect.enable)
  674.         {
  675.             mvwprintw(effectWindow, i + 1, 1, "0x%x: DISABLED", i);
  676.         }
  677.         else
  678.         {
  679.             char eff[20];
  680.             switch(effect.effect)
  681.             {
  682.                 case 0x0:
  683.                     strcpy(eff, "ARPEGGIO:  ");
  684.                     break;
  685.                 case 0x1:
  686.                     strcpy(eff, "PORT UP:   ");
  687.                     break;
  688.                 case 0x2:
  689.                     strcpy(eff, "PORT DOWN: ");
  690.                     break;
  691.                 case 0x3:
  692.                     strcpy(eff, "PORTAMENTO:");
  693.                     break;
  694.                 case 0x4:
  695.                     strcpy(eff, "VIBRATO:   ");
  696.                     break;
  697.                 case 0x5:
  698.                     strcpy(eff, "WAVEFORM:  ");
  699.                     break;
  700.                 case 0x6:
  701.                     strcpy(eff, "DUTY CYCLE:");
  702.                     break;
  703.                 case 0x7:
  704.                     strcpy(eff, "TREMOLO:   ");
  705.                     break;
  706.                 case 0x8:
  707.                     strcpy(eff, "PWM:       ");
  708.                     break;
  709.                 case 0x9:
  710.                     strcpy(eff, "PITCH:     ");
  711.                     break;
  712.                 case 0xA:
  713.                     strcpy(eff, "VOL UP:    ");
  714.                     break;
  715.                 case 0xB:
  716.                     strcpy(eff, "VOL DOWN:  ");
  717.                     break;
  718.                 case 0xC:
  719.                     strcpy(eff, "SET VOL:   ");
  720.                     break;
  721.                 case 0xD:
  722.                     strcpy(eff, "ATCK/DECAY:");
  723.                     break;
  724.                 case 0xE:
  725.                     strcpy(eff, "SUS/RELEAS:");
  726.                     break;
  727.                 case 0xF:
  728.                     strcpy(eff, "FINE TUNE: ");
  729.                     break;
  730.             }
  731.             mvwprintw(effectWindow, i + 1, 1, "0x%x: (0x%x) %s 0x%x%x", i, effect.effect, eff, (effect.argument & 0xF0) >> 4, effect.argument & 0xF);
  732.         }
  733.     }
  734.    
  735.     wrefresh(effectWindow);
  736.     placeCursor();
  737. }
  738.  
  739. void drawTrackerWindow()
  740. {
  741.     wclear(trackerWindow);
  742.     wattrset(trackerWindow, A_NORMAL);
  743.     if(curWindow == WIN_TRACKER && curMode == MODE_EDIT) wattrset(trackerWindow, A_REVERSE);
  744.     wattron(trackerWindow, A_BOLD);
  745.     box(trackerWindow, 0, 0);
  746.     wattroff(trackerWindow, A_BOLD);
  747.     printTitle(trackerWindow, "Tracker");
  748.     wattrset(trackerWindow, A_NORMAL);
  749.    
  750.     int i;
  751.     for(i = -2 + trackerScroll; i <= 32 && i < h2 - 4 + trackerScroll; i++)
  752.     {
  753.         wattrset(trackerWindow, A_BOLD);
  754.         if(i - trackerScroll >= 0 && i - trackerScroll < 32)
  755.         {
  756.             if(curFrame == i) wattron(trackerWindow, A_REVERSE);
  757.             mvwprintw(trackerWindow, i + 3 - trackerScroll, 1, "0x%x%x ", (i & 0xF0) >> 4, i & 0xF);
  758.         }
  759.         else if(i - trackerScroll == -2)
  760.         {
  761.             mvwprintw(trackerWindow, i + 3 - trackerScroll, 1, "(0x%x)", curOrder);
  762.         }
  763.         else if(i - trackerScroll == -1 || i == 32)
  764.         {
  765.             wattrset(trackerWindow, A_NORMAL);
  766.             wmove(trackerWindow, i + 3 - trackerScroll, 1);
  767.             int a;
  768.             for(a = 0; a < 5; a++)
  769.             {
  770.                 waddch(trackerWindow, ACS_HLINE);
  771.             }
  772.         }
  773.         wattrset(trackerWindow, A_NORMAL);
  774.         waddch(trackerWindow, ACS_VLINE);
  775.        
  776.         int a;
  777.         for(a = 0; a < 4; a++)
  778.         {
  779.             if(i - trackerScroll == -2)
  780.             {
  781.                 wattrset(trackerWindow, A_BOLD);
  782.                 if(curOsc == a) wattron(trackerWindow, A_REVERSE);
  783.                 mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "Osc #%i   ", a + 1);
  784.                 wattrset(trackerWindow, A_NORMAL);
  785.             }
  786.             else if(i - trackerScroll == -1 || i == 32)
  787.             {
  788.                 wmove(trackerWindow, i + 3 - trackerScroll, a * 10 + 7);
  789.                 int a;
  790.                 for(a = 0; a < 9; a++)
  791.                 {
  792.                     waddch(trackerWindow, ACS_HLINE);
  793.                 }
  794.             }
  795.             else
  796.             {
  797.                 Entry entry = song.orders[curOrder].frames[i].entries[a];
  798.                 wattrset(trackerWindow, curFrame == i && curOsc == a && curCol == 0 ? A_REVERSE : A_NORMAL);
  799.                 switch(entry.noteCommand.note)
  800.                 {
  801.                     case 0x0:
  802.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "---");
  803.                         break;
  804.                     case 0x1:
  805.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "RES");
  806.                         break;
  807.                     case 0x2:
  808.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "+++");
  809.                         break;
  810.                     case 0x3:
  811.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "xxx");
  812.                         break;
  813.                     case 0x4:
  814.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "C-%x", entry.noteCommand.octave);
  815.                         break;
  816.                     case 0x5:
  817.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "C#%x", entry.noteCommand.octave);
  818.                         break;
  819.                     case 0x6:
  820.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "D-%x", entry.noteCommand.octave);
  821.                         break;
  822.                     case 0x7:
  823.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "D#%x", entry.noteCommand.octave);
  824.                         break;
  825.                     case 0x8:
  826.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "E-%x", entry.noteCommand.octave);
  827.                         break;
  828.                     case 0x9:
  829.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "F-%x", entry.noteCommand.octave);
  830.                         break;
  831.                     case 0xA:
  832.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "F#%x", entry.noteCommand.octave);
  833.                         break;
  834.                     case 0xB:
  835.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "G-%x", entry.noteCommand.octave);
  836.                         break;
  837.                     case 0xC:
  838.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "G#%x", entry.noteCommand.octave);
  839.                         break;
  840.                     case 0xD:
  841.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "A-%x", entry.noteCommand.octave);
  842.                         break;
  843.                     case 0xE:
  844.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "A#%x", entry.noteCommand.octave);
  845.                         break;
  846.                     case 0xF:
  847.                         mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "B-%x", entry.noteCommand.octave);
  848.                         break;
  849.                 }
  850.                 wattrset(trackerWindow, curFrame == i && curOsc == a && curCol == 1 ? A_REVERSE : A_NORMAL);
  851.                 if(entry.noteCommand.applyInstrument)
  852.                 {
  853.                     wprintw(trackerWindow, "%x", entry.noteCommand.instrument);
  854.                 }
  855.                 else
  856.                 {
  857.                     wprintw(trackerWindow, "-", entry.noteCommand.instrument);
  858.                 }
  859.                 wattrset(trackerWindow, curFrame == i && curOsc == a && curCol == 2 ? A_REVERSE : A_NORMAL);
  860.                 if(entry.noteCommand.volume)
  861.                 {
  862.                     wprintw(trackerWindow, "%x%x", entry.noteCommand.volume >> 4, entry.noteCommand.volume & 0xF);
  863.                 }
  864.                 else
  865.                 {
  866.                     wprintw(trackerWindow, "--");
  867.                 }
  868.                 if(entry.effect.enable)
  869.                 {
  870.                     wattrset(trackerWindow, curFrame == i && curOsc == a && curCol == 3 ? A_REVERSE : A_NORMAL);
  871.                     wprintw(trackerWindow, "%x", entry.effect.effect & 0xF);
  872.                     wattrset(trackerWindow, curFrame == i && curOsc == a && curCol == 4 ? A_REVERSE : A_NORMAL);
  873.                     wprintw(trackerWindow, "%x%x", entry.effect.argument >> 4, entry.effect.argument & 0xF);
  874.                 }
  875.                 else
  876.                 {
  877.                     wattrset(trackerWindow, curFrame == i && curOsc == a && curCol == 3 ? A_REVERSE : A_NORMAL);
  878.                     wprintw(trackerWindow, "-");
  879.                     wattrset(trackerWindow, curFrame == i && curOsc == a && curCol == 4 ? A_REVERSE : A_NORMAL);
  880.                     wprintw(trackerWindow, "--");
  881.                 }
  882.             }
  883.             wattrset(trackerWindow, A_NORMAL);
  884.             waddch(trackerWindow, ACS_VLINE);
  885.         }
  886.     }
  887.    
  888.     wrefresh(trackerWindow);
  889.     placeCursor();
  890. }
  891.  
  892. void drawWindows()
  893. {
  894.     drawOrderWindow();
  895.     drawInstrumentWindow();
  896.     drawEffectWindow();
  897.     drawTrackerWindow();
  898.     placeCursor();
  899.     refresh();
  900. }
  901.  
  902. void spam(int c, int y)
  903. {
  904.     move(y, 0);
  905.     int i;
  906.     for(i = 0; i < COLS; i++)
  907.     {
  908.         printw("%c", c);
  909.     }
  910. }
  911.  
  912. void drawStatus()
  913. {
  914.     char modeString[32];
  915.     switch(curMode)
  916.     {
  917.         case MODE_EDIT:
  918.             strcpy(modeString, "Edit");
  919.             break;
  920.         case MODE_PLAY:
  921.             strcpy(modeString, "Play");
  922.             break;
  923.         case MODE_JAM:
  924.             strcpy(modeString, "Jam");
  925.             break;
  926.     }
  927.     attrset(A_NORMAL);
  928.     spam(' ', LINES - 1);
  929.     mvprintw(LINES - 1, 0, "MODE: %s | OCTAVE: %i | SPEED: %i FPS | REPEAT: 0x%x | ORDERS: %i | INSTRUMENTS: %i", modeString, curOctave, song.fps, song.repeat, song.orderCount, song.instrumentCount);
  930.     placeCursor();
  931.     refresh();
  932. }
  933.  
  934. void initWindows()
  935. {
  936.     w1 = COLS / 3;
  937.     h1 = 10;
  938.     w2 = w1 * 3;
  939.     h2 = LINES - h1 - 1;
  940.     orderWindow = newwin(h1, w1, 0, 0);
  941.     instrumentWindow = newwin(h1, w1, 0, w1);
  942.     effectWindow = newwin(h1, w1, 0, w1 * 2);
  943.     trackerWindow = newwin(h2, w2, h1, 0);
  944.    
  945.     clear();
  946.     refresh();
  947.     drawWindows();
  948.     drawStatus();
  949.     placeCursor();
  950.     refresh();
  951. }
  952.  
  953. void scrollTracker()
  954. {
  955.     while(curFrame > h2 / 2 + trackerScroll) trackerScroll++;
  956.     while(curFrame < trackerScroll) trackerScroll--;
  957. }
  958.  
  959. void down()
  960. {
  961.     curFrame = (curFrame + 1) % 32;
  962.     scrollTracker();
  963. }
  964.  
  965. void up()
  966. {
  967.     curFrame--;
  968.     if(curFrame < 0) curFrame = 31;
  969.     scrollTracker();
  970. }
  971.  
  972. Order clipboard;
  973.  
  974. void editInput(int c)
  975. {
  976.     Entry *entry = &song.orders[curOrder].frames[curFrame].entries[curOsc];
  977.     switch(c)
  978.     {
  979.         case '\t':
  980.             curWindow = (curWindow + 1) % 4;
  981.             drawWindows();
  982.             break;
  983.         default:
  984.             switch(curWindow)
  985.             {
  986.                 case WIN_ORDER:
  987.                     switch(c)
  988.                     {
  989.                         case KEY_DOWN:
  990.                             curOrder = (curOrder + 1) % song.orderCount;
  991.                             while(curOrder >= orderScroll + h1 - 2)
  992.                             {
  993.                                 orderScroll++;
  994.                             }
  995.                             while(curOrder < orderScroll)
  996.                             {
  997.                                 orderScroll--;
  998.                             }
  999.                             drawOrderWindow();
  1000.                             drawTrackerWindow();
  1001.                             break;
  1002.                         case KEY_UP:
  1003.                             curOrder = (curOrder - 1);
  1004.                             while(curOrder < 0) curOrder += song.orderCount;
  1005.                             while(curOrder >= orderScroll + h1 - 2)
  1006.                             {
  1007.                                 orderScroll++;
  1008.                             }
  1009.                             while(curOrder < orderScroll)
  1010.                             {
  1011.                                 orderScroll--;
  1012.                             }
  1013.                             drawOrderWindow();
  1014.                             drawTrackerWindow();
  1015.                             break;
  1016.                         case 'r':
  1017.                             song.repeat = curOrder;
  1018.                             drawOrderWindow();
  1019.                             break;
  1020.                         case 'c':
  1021.                             clipboard = song.orders[curOrder];
  1022.                             break;
  1023.                         case 'v':
  1024.                             song.orders[curOrder] = clipboard;
  1025.                             drawTrackerWindow();
  1026.                         case '=':
  1027.                             song.orderCount++;
  1028.                             if(song.orderCount > MAX_ORDERS) song.orderCount = MAX_ORDERS;
  1029.                             drawOrderWindow();
  1030.                             drawStatus();
  1031.                             break;
  1032.                         case '-':
  1033.                             song.orderCount--;
  1034.                             if(song.orderCount <= 0) song.orderCount = 1;
  1035.                             if(curOrder >= song.orderCount) curOrder = song.orderCount - 1;
  1036.                             while(curOrder >= orderScroll + h1 - 2)
  1037.                             {
  1038.                                 orderScroll++;
  1039.                             }
  1040.                             while(curOrder < orderScroll)
  1041.                             {
  1042.                                 orderScroll--;
  1043.                             }
  1044.                             if(song.repeat >= song.orderCount) song.repeat--;
  1045.                             drawOrderWindow();
  1046.                             drawStatus();
  1047.                             break;
  1048.                     }
  1049.                     break;
  1050.                 case WIN_INSTR:
  1051.                     switch(c)
  1052.                     {
  1053.                         case KEY_DOWN:
  1054.                             curInstrument = (curInstrument + 1) % song.instrumentCount;
  1055.                             while(curInstrument >= instrumentScroll + h1 - 2)
  1056.                             {
  1057.                                 instrumentScroll++;
  1058.                             }
  1059.                             while(curInstrument < instrumentScroll)
  1060.                             {
  1061.                                 instrumentScroll--;
  1062.                             }
  1063.                             drawInstrumentWindow();
  1064.                             drawEffectWindow();
  1065.                             break;
  1066.                         case KEY_UP:
  1067.                             curInstrument = (curInstrument - 1);
  1068.                             while(curInstrument < 0) curInstrument += song.instrumentCount;
  1069.                             while(curInstrument >= instrumentScroll + h1 - 2)
  1070.                             {
  1071.                                 instrumentScroll++;
  1072.                             }
  1073.                             while(curInstrument < instrumentScroll)
  1074.                             {
  1075.                                 instrumentScroll--;
  1076.                             }
  1077.                             drawInstrumentWindow();
  1078.                             drawEffectWindow();
  1079.                             break;
  1080.                         case '=':
  1081.                             song.instrumentCount++;
  1082.                             if(song.instrumentCount > MAX_INSTRUMENTS) song.instrumentCount = MAX_INSTRUMENTS;
  1083.                             drawInstrumentWindow();
  1084.                             drawStatus();
  1085.                             break;
  1086.                         case '-':
  1087.                             song.instrumentCount--;
  1088.                             if(song.instrumentCount <= 0) song.instrumentCount = 1;
  1089.                             if(curInstrument >= song.instrumentCount) curInstrument = song.instrumentCount - 1;
  1090.                             while(curInstrument >= instrumentScroll + h1 - 2)
  1091.                             {
  1092.                                 orderScroll++;
  1093.                             }
  1094.                             while(curInstrument < instrumentScroll)
  1095.                             {
  1096.                                 instrumentScroll--;
  1097.                             }
  1098.                             drawInstrumentWindow();
  1099.                             drawStatus();
  1100.                             break;
  1101.                     }
  1102.                     break;
  1103.                 case WIN_EFFECT:
  1104.                     switch(c)
  1105.                     {
  1106.                         case KEY_DOWN:
  1107.                             curEffect = (curEffect + 1) % 8;
  1108.                             drawEffectWindow();
  1109.                             break;
  1110.                         case KEY_UP:
  1111.                             curEffect = (curEffect - 1);
  1112.                             while(curEffect < 0) curEffect += 8;
  1113.                             drawEffectWindow();
  1114.                             break;
  1115.                         case KEY_RIGHT:
  1116.                             if(song.instruments[curInstrument].effects[curEffect].enable)
  1117.                             {
  1118.                                 song.instruments[curInstrument].effects[curEffect].effect++;
  1119.                                 if(song.instruments[curInstrument].effects[curEffect].effect > 0xF) song.instruments[curInstrument].effects[curEffect].effect = 0xF;
  1120.                             }
  1121.                             else
  1122.                             {
  1123.                                 song.instruments[curInstrument].effects[curEffect].enable = 1;
  1124.                             }
  1125.                             drawEffectWindow();
  1126.                             break;
  1127.                         case KEY_LEFT:
  1128.                             if(song.instruments[curInstrument].effects[curEffect].enable)
  1129.                             {
  1130.                                 song.instruments[curInstrument].effects[curEffect].effect--;
  1131.                                 if(song.instruments[curInstrument].effects[curEffect].effect > 0xF)
  1132.                                 {
  1133.                                     song.instruments[curInstrument].effects[curEffect].effect = 0;
  1134.                                     song.instruments[curInstrument].effects[curEffect].enable = 0;
  1135.                                 }
  1136.                                 drawEffectWindow();
  1137.                             }
  1138.                             break;
  1139.                         case '=':
  1140.                             if(song.instruments[curInstrument].effects[curEffect].enable)
  1141.                             {
  1142.                                 song.instruments[curInstrument].effects[curEffect].argument++;
  1143.                                 drawEffectWindow();
  1144.                             }
  1145.                             break;
  1146.                         case '-':
  1147.                             if(song.instruments[curInstrument].effects[curEffect].enable)
  1148.                             {
  1149.                                 song.instruments[curInstrument].effects[curEffect].argument--;
  1150.                                 drawEffectWindow();
  1151.                             }
  1152.                             break;
  1153.                         case ']':
  1154.                             if(song.instruments[curInstrument].effects[curEffect].enable)
  1155.                             {
  1156.                                 song.instruments[curInstrument].effects[curEffect].argument += 0x10;
  1157.                                 drawEffectWindow();
  1158.                             }
  1159.                             break;
  1160.                         case '[':
  1161.                             if(song.instruments[curInstrument].effects[curEffect].enable)
  1162.                             {
  1163.                                 song.instruments[curInstrument].effects[curEffect].argument -= 0x10;
  1164.                                 drawEffectWindow();
  1165.                             }
  1166.                             break;
  1167.                         }
  1168.                     break;
  1169.                 case WIN_TRACKER:
  1170.                     switch(c)
  1171.                     {
  1172.                         case KEY_F(1):
  1173.                             curOsc = 0;
  1174.                             drawTrackerWindow();
  1175.                             break;
  1176.                         case KEY_F(2):
  1177.                             curOsc = 1;
  1178.                             drawTrackerWindow();
  1179.                             break;
  1180.                         case KEY_F(3):
  1181.                             curOsc = 2;
  1182.                             drawTrackerWindow();
  1183.                             break;
  1184.                         case KEY_F(4):
  1185.                             curOsc = 3;
  1186.                             drawTrackerWindow();
  1187.                             break;
  1188.                         case KEY_RIGHT:
  1189.                             curCol++;
  1190.                             if(curCol > 4)
  1191.                             {
  1192.                                 curCol = 0;
  1193.                                 curOsc = (curOsc + 1) % 4;
  1194.                             }
  1195.                             drawTrackerWindow();
  1196.                             break;
  1197.                         case KEY_LEFT:
  1198.                             curCol--;
  1199.                             if(curCol < 0)
  1200.                             {
  1201.                                 curCol = 4;
  1202.                                 curOsc--;
  1203.                                 if(curOsc < 0) curOsc = 3;
  1204.                             }
  1205.                             drawTrackerWindow();
  1206.                             break;
  1207.                         case KEY_DOWN:
  1208.                             down();
  1209.                             drawTrackerWindow();
  1210.                             break;
  1211.                         case KEY_UP:
  1212.                             up();
  1213.                             drawTrackerWindow();
  1214.                             break;
  1215.                         case 'p':
  1216.                             playEntry(entry, curOsc);
  1217.                             break;
  1218.                         case KEY_BACKSPACE:
  1219.                             up();
  1220.                         default:
  1221.                             switch(curCol)
  1222.                             {
  1223.                                 case 0:
  1224.                                     switch(c)
  1225.                                     {
  1226.                                         case KEY_BACKSPACE:
  1227.                                             entry->noteCommand.note = NOTE_NULL;
  1228.                                             break;
  1229.                                         case '`':
  1230.                                             if(entry->noteCommand.note == NOTE_OFF)
  1231.                                             {
  1232.                                                 entry->noteCommand.note = NOTE_ON;
  1233.                                             }
  1234.                                             else
  1235.                                             {
  1236.                                                 entry->noteCommand.note = NOTE_OFF;
  1237.                                             }
  1238.                                             down();
  1239.                                             break;
  1240.                                         case '0':
  1241.                                             entry->noteCommand.octave = 0;
  1242.                                             break;
  1243.                                         case '1':
  1244.                                             entry->noteCommand.octave = 1;
  1245.                                             break;
  1246.                                         case '2':
  1247.                                             entry->noteCommand.octave = 2;
  1248.                                             break;
  1249.                                         case '3':
  1250.                                             entry->noteCommand.octave = 3;
  1251.                                             break;
  1252.                                         case '4':
  1253.                                             entry->noteCommand.octave = 4;
  1254.                                             break;
  1255.                                         case '5':
  1256.                                             entry->noteCommand.octave = 5;
  1257.                                             break;
  1258.                                         case '6':
  1259.                                             entry->noteCommand.octave = 6;
  1260.                                             break;
  1261.                                         case '7':
  1262.                                             entry->noteCommand.octave = 7;
  1263.                                             break;
  1264.                                         case 'a':
  1265.                                             entry->noteCommand.octave = curOctave;
  1266.                                             entry->noteCommand.note = NOTE_C;
  1267.                                             down();
  1268.                                             break;
  1269.                                         case 'w':
  1270.                                             entry->noteCommand.octave = curOctave;
  1271.                                             entry->noteCommand.note = NOTE_Cs;
  1272.                                             down();
  1273.                                             break;
  1274.                                         case 's':
  1275.                                             entry->noteCommand.octave = curOctave;
  1276.                                             entry->noteCommand.note = NOTE_D;
  1277.                                             down();
  1278.                                             break;
  1279.                                         case 'e':
  1280.                                             entry->noteCommand.octave = curOctave;
  1281.                                             entry->noteCommand.note = NOTE_Ds;
  1282.                                             down();
  1283.                                             break;
  1284.                                         case 'd':
  1285.                                             entry->noteCommand.octave = curOctave;
  1286.                                             entry->noteCommand.note = NOTE_E;
  1287.                                             down();
  1288.                                             break;
  1289.                                         case 'f':
  1290.                                             entry->noteCommand.octave = curOctave;
  1291.                                             entry->noteCommand.note = NOTE_F;
  1292.                                             down();
  1293.                                             break;
  1294.                                         case 't':
  1295.                                             entry->noteCommand.octave = curOctave;
  1296.                                             entry->noteCommand.note = NOTE_Fs;
  1297.                                             down();
  1298.                                             break;
  1299.                                         case 'g':
  1300.                                             entry->noteCommand.octave = curOctave;
  1301.                                             entry->noteCommand.note = NOTE_G;
  1302.                                             down();
  1303.                                             break;
  1304.                                         case 'y':
  1305.                                             entry->noteCommand.octave = curOctave;
  1306.                                             entry->noteCommand.note = NOTE_Gs;
  1307.                                             down();
  1308.                                             break;
  1309.                                         case 'h':
  1310.                                             entry->noteCommand.octave = curOctave;
  1311.                                             entry->noteCommand.note = NOTE_A;
  1312.                                             down();
  1313.                                             break;
  1314.                                         case 'u':
  1315.                                             entry->noteCommand.octave = curOctave;
  1316.                                             entry->noteCommand.note = NOTE_As;
  1317.                                             down();
  1318.                                             break;
  1319.                                         case 'j':
  1320.                                             entry->noteCommand.octave = curOctave;
  1321.                                             entry->noteCommand.note = NOTE_B;
  1322.                                             down();
  1323.                                             break;
  1324.                                         case 'k':
  1325.                                             entry->noteCommand.octave = curOctave + 1;
  1326.                                             entry->noteCommand.note = NOTE_C;
  1327.                                             down();
  1328.                                             break;
  1329.                                         case 'r':
  1330.                                             entry->noteCommand.note = NOTE_RESET;
  1331.                                             break;
  1332.                                         case '=':
  1333.                                             if(entry->noteCommand.note == NOTE_B)
  1334.                                             {
  1335.                                                 entry->noteCommand.note = NOTE_C;
  1336.                                                 entry->noteCommand.octave = (entry->noteCommand.octave + 1) % 8;
  1337.                                             }
  1338.                                             else if(entry->noteCommand.note > 3)
  1339.                                             {
  1340.                                                 entry->noteCommand.note++;
  1341.                                             }
  1342.                                             break;
  1343.                                         case '-':
  1344.                                             if(entry->noteCommand.note == 4)
  1345.                                             {
  1346.                                                 entry->noteCommand.note = 15;
  1347.                                                 if(entry->noteCommand.octave == 0)
  1348.                                                 {
  1349.                                                     entry->noteCommand.octave = 7;
  1350.                                                 }
  1351.                                                 else
  1352.                                                 {
  1353.                                                     entry->noteCommand.octave--;
  1354.                                                 }
  1355.                                             }
  1356.                                             else if(entry->noteCommand.note > 4)
  1357.                                             {
  1358.                                                 entry->noteCommand.note--;
  1359.                                             }
  1360.                                             break;
  1361.                                         case ']':
  1362.                                             entry->noteCommand.octave = (entry->noteCommand.octave + 1) % 8;
  1363.                                             break;
  1364.                                         case '[':
  1365.                                             if(entry->noteCommand.octave == 0)
  1366.                                             {
  1367.                                                 entry->noteCommand.octave = 7;
  1368.                                             }
  1369.                                             else
  1370.                                             {
  1371.                                                 entry->noteCommand.octave--;
  1372.                                             }
  1373.                                             break;
  1374.                                     }
  1375.                                     break;
  1376.                                 case 1:
  1377.                                     switch(c)
  1378.                                     {
  1379.                                         case KEY_BACKSPACE:
  1380.                                             entry->noteCommand.applyInstrument = 0;
  1381.                                             break;
  1382.                                         case '0':
  1383.                                             entry->noteCommand.instrument = 0;
  1384.                                             entry->noteCommand.applyInstrument = 1;
  1385.                                             down();
  1386.                                             break;
  1387.                                         case '1':
  1388.                                             entry->noteCommand.instrument = 1;
  1389.                                             entry->noteCommand.applyInstrument = 1;
  1390.                                             down();
  1391.                                             break;
  1392.                                         case '2':
  1393.                                             entry->noteCommand.instrument = 2;
  1394.                                             entry->noteCommand.applyInstrument = 1;
  1395.                                             down();
  1396.                                             break;
  1397.                                         case '3':
  1398.                                             entry->noteCommand.instrument = 3;
  1399.                                             entry->noteCommand.applyInstrument = 1;
  1400.                                             down();
  1401.                                             break;
  1402.                                         case '4':
  1403.                                             entry->noteCommand.instrument = 4;
  1404.                                             entry->noteCommand.applyInstrument = 1;
  1405.                                             down();
  1406.                                             break;
  1407.                                         case '5':
  1408.                                             entry->noteCommand.instrument = 5;
  1409.                                             entry->noteCommand.applyInstrument = 1;
  1410.                                             down();
  1411.                                             break;
  1412.                                         case '6':
  1413.                                             entry->noteCommand.instrument = 6;
  1414.                                             entry->noteCommand.applyInstrument = 1;
  1415.                                             down();
  1416.                                             break;
  1417.                                         case '7':
  1418.                                             entry->noteCommand.instrument = 7;
  1419.                                             entry->noteCommand.applyInstrument = 1;
  1420.                                             down();
  1421.                                             break;
  1422.                                         case '=':
  1423.                                             entry->noteCommand.instrument = (entry->noteCommand.instrument + 1) % 8;
  1424.                                             break;
  1425.                                         case '-':
  1426.                                             if(entry->noteCommand.instrument == 0)
  1427.                                             {
  1428.                                                 entry->noteCommand.instrument = 7;
  1429.                                             }
  1430.                                             else
  1431.                                             {
  1432.                                                 entry->noteCommand.instrument--;
  1433.                                             }
  1434.                                             break;
  1435.                                     }
  1436.                                     break;
  1437.                                 case 2:
  1438.                                     switch(c)
  1439.                                     {
  1440.                                         case KEY_BACKSPACE:
  1441.                                             entry->noteCommand.volume = 0;
  1442.                                             break;
  1443.                                         case '0':
  1444.                                             entry->noteCommand.volume = 0;
  1445.                                             down();
  1446.                                             break;
  1447.                                         case '`':
  1448.                                             entry->noteCommand.volume = 31;
  1449.                                             down();
  1450.                                             break;
  1451.                                         case '=':
  1452.                                             entry->noteCommand.volume = (entry->noteCommand.volume + 1) % 32;
  1453.                                             break;
  1454.                                         case '-':
  1455.                                             if(entry->noteCommand.volume == 0)
  1456.                                             {
  1457.                                                 entry->noteCommand.volume = 31;
  1458.                                             }
  1459.                                             else
  1460.                                             {
  1461.                                                 entry->noteCommand.volume--;
  1462.                                             }
  1463.                                             break;
  1464.                                         case ']':
  1465.                                             entry->noteCommand.volume = (entry->noteCommand.volume + 0x10) % 32;
  1466.                                             break;
  1467.                                         case '[':
  1468.                                             if(entry->noteCommand.volume <= 0x10)
  1469.                                             {
  1470.                                                 entry->noteCommand.volume = 31;
  1471.                                             }
  1472.                                             else
  1473.                                             {
  1474.                                                 entry->noteCommand.volume -= 0x10;
  1475.                                             }
  1476.                                             break;
  1477.                                     }
  1478.                                     break;
  1479.                                 case 3:
  1480.                                     switch(c)
  1481.                                     {
  1482.                                         case KEY_BACKSPACE:
  1483.                                             entry->effect.enable = 0;
  1484.                                             break;
  1485.                                         case '0':
  1486.                                             entry->effect.effect = 0;
  1487.                                             entry->effect.enable = 1;
  1488.                                             down();
  1489.                                             break;
  1490.                                         case '1':
  1491.                                             entry->effect.effect = 1;
  1492.                                             entry->effect.enable = 1;
  1493.                                             down();
  1494.                                             break;
  1495.                                         case '2':
  1496.                                             entry->effect.effect = 2;
  1497.                                             entry->effect.enable = 1;
  1498.                                             down();
  1499.                                             break;
  1500.                                         case '3':
  1501.                                             entry->effect.effect = 3;
  1502.                                             entry->effect.enable = 1;
  1503.                                             down();
  1504.                                             break;
  1505.                                         case '4':
  1506.                                             entry->effect.effect = 4;
  1507.                                             entry->effect.enable = 1;
  1508.                                             down();
  1509.                                             break;
  1510.                                         case '5':
  1511.                                             entry->effect.effect = 5;
  1512.                                             entry->effect.enable = 1;
  1513.                                             down();
  1514.                                             break;
  1515.                                         case '6':
  1516.                                             entry->effect.effect = 6;
  1517.                                             entry->effect.enable = 1;
  1518.                                             down();
  1519.                                             break;
  1520.                                         case '7':
  1521.                                             entry->effect.effect = 7;
  1522.                                             entry->effect.enable = 1;
  1523.                                             down();
  1524.                                             break;
  1525.                                         case '8':
  1526.                                             entry->effect.effect = 8;
  1527.                                             entry->effect.enable = 1;
  1528.                                             down();
  1529.                                             break;
  1530.                                         case '9':
  1531.                                             entry->effect.effect = 9;
  1532.                                             entry->effect.enable = 1;
  1533.                                             down();
  1534.                                             break;
  1535.                                         case 'a':
  1536.                                             entry->effect.effect = 0xA;
  1537.                                             entry->effect.enable = 1;
  1538.                                             down();
  1539.                                             break;
  1540.                                         case 'b':
  1541.                                             entry->effect.effect = 0xB;
  1542.                                             entry->effect.enable = 1;
  1543.                                             down();
  1544.                                             break;
  1545.                                         case 'c':
  1546.                                             entry->effect.effect = 0xC;
  1547.                                             entry->effect.enable = 1;
  1548.                                             down();
  1549.                                             break;
  1550.                                         case 'd':
  1551.                                             entry->effect.effect = 0xD;
  1552.                                             entry->effect.enable = 1;
  1553.                                             down();
  1554.                                             break;
  1555.                                         case 'e':
  1556.                                             entry->effect.effect = 0xE;
  1557.                                             entry->effect.enable = 1;
  1558.                                             down();
  1559.                                             break;
  1560.                                         case 'f':
  1561.                                             entry->effect.effect = 0xF;
  1562.                                             entry->effect.enable = 1;
  1563.                                             down();
  1564.                                             break;
  1565.                                         case '=':
  1566.                                             entry->effect.effect = (entry->effect.effect + 1) % 0x10;
  1567.                                             entry->effect.enable = 1;
  1568.                                             break;
  1569.                                         case '-':
  1570.                                             if(entry->effect.effect == 0)
  1571.                                             {
  1572.                                                 entry->effect.effect = 0xF;
  1573.                                             }
  1574.                                             else
  1575.                                             {
  1576.                                                 entry->effect.effect--;
  1577.                                             }
  1578.                                             entry->effect.enable = 1;
  1579.                                             break;
  1580.                                     }
  1581.                                     break;
  1582.                                 case 4:
  1583.                                     switch(c)
  1584.                                     {
  1585.                                         case KEY_BACKSPACE:
  1586.                                             entry->effect.enable = 0;
  1587.                                             break;
  1588.                                         case '0':
  1589.                                             entry->effect.argument = 0;
  1590.                                             entry->effect.enable = 1;
  1591.                                             down();
  1592.                                             break;
  1593.                                         case '=':
  1594.                                             entry->effect.argument++;
  1595.                                             entry->effect.enable = 1;
  1596.                                             break;
  1597.                                         case '-':
  1598.                                             entry->effect.argument--;
  1599.                                             entry->effect.enable = 1;
  1600.                                             break;
  1601.                                         case ']':
  1602.                                             entry->effect.argument += 0x10;
  1603.                                             entry->effect.enable = 1;
  1604.                                             break;
  1605.                                         case '[':
  1606.                                             entry->effect.argument -= 0x10;
  1607.                                             entry->effect.enable = 1;
  1608.                                             break;
  1609.                                     }
  1610.                                     break;
  1611.                             }
  1612.                             drawTrackerWindow();
  1613.                     }
  1614.                     break;
  1615.             }
  1616.     }
  1617. }
  1618.  
  1619. void playInput(int c)
  1620. {
  1621.    
  1622. }
  1623.  
  1624. void jamInput(int c)
  1625. {
  1626.    
  1627. }
  1628.  
  1629. void editMode()
  1630. {
  1631.     curMode = MODE_EDIT;
  1632.     drawWindows();
  1633.     drawStatus();
  1634. }
  1635.  
  1636. void broadcastEffect(Effect effect)
  1637. {
  1638.     sendEffectCommand(&effect, 0);
  1639.     sendEffectCommand(&effect, 1);
  1640.     sendEffectCommand(&effect, 2);
  1641.     sendEffectCommand(&effect, 3);
  1642. }
  1643.  
  1644. void resetEffects()
  1645. {
  1646.     broadcastEffect(newEffect(0x0, 0x00));
  1647.     broadcastEffect(newEffect(0x1, 0x00));
  1648.     broadcastEffect(newEffect(0x2, 0x00));
  1649.     broadcastEffect(newEffect(0x3, 0x00));
  1650.     broadcastEffect(newEffect(0x4, 0x00));
  1651.     broadcastEffect(newEffect(0x5, 0x00));
  1652.     broadcastEffect(newEffect(0x6, 0x7F));
  1653.     broadcastEffect(newEffect(0x7, 0x00));
  1654.     broadcastEffect(newEffect(0x8, 0x00));
  1655.     broadcastEffect(newEffect(0x9, 0x00));
  1656.     broadcastEffect(newEffect(0xA, 0x00));
  1657.     broadcastEffect(newEffect(0xB, 0x00));
  1658.     broadcastEffect(newEffect(0xC, 0xFF));
  1659.     broadcastEffect(newEffect(0xD, 0x00));
  1660.     broadcastEffect(newEffect(0xE, 0xF0));
  1661.     broadcastEffect(newEffect(0xF, 0x00));
  1662. }
  1663.  
  1664. Frame quietFrame;
  1665.  
  1666. void reset()
  1667. {
  1668.     playFrame(&quietFrame);
  1669.     resetEffects();
  1670. }
  1671.  
  1672. int playing;
  1673.  
  1674. void playOrder(Order *order, int fps)
  1675. {
  1676.     int i;
  1677.     for(i = 0; i < sizeof(order->frames) / sizeof(Frame); i++)
  1678.     {
  1679.         curFrame = i;
  1680.         scrollTracker();
  1681.         drawTrackerWindow();
  1682.        
  1683.         playFrame(&order->frames[i]);
  1684.         usleep(1000000 / fps);
  1685.        
  1686.         char c = getch();
  1687.         if(c == '\n' || c == ' ' || c == KEY_F(8))
  1688.         {
  1689.             playing = 0;
  1690.             reset();
  1691.             editMode();
  1692.             break;
  1693.         }
  1694.     }
  1695. }
  1696.  
  1697. void playMode()
  1698. {
  1699.     curMode = MODE_PLAY;
  1700.     drawWindows();
  1701.     drawStatus();
  1702.    
  1703.     int i;
  1704.     playing = 1;
  1705.     for(i = 0; playing; i++)
  1706.     {
  1707.         if(i == song.orderCount) i = song.repeat;
  1708.         curOrder = i;
  1709.         drawOrderWindow();
  1710.         Order order = song.orders[i];
  1711.         playOrder(&order, song.fps);
  1712.     }
  1713. }
  1714.  
  1715. void jamMode()
  1716. {
  1717.     curMode = MODE_JAM;
  1718.     drawWindows();
  1719.     drawStatus();
  1720. }
  1721.  
  1722. void playCurrentFrame()
  1723. {
  1724.     Frame f = song.orders[curOrder].frames[curFrame];
  1725.     playFrame(&f);
  1726. }
  1727.  
  1728. void playCurrentOrder()
  1729. {
  1730.     Order o = song.orders[curOrder];
  1731.     playOrder(&o, song.fps);
  1732. }
  1733.  
  1734. void save()
  1735. {
  1736.     FILE *fp;
  1737.     fp = fopen("chiptune.sav", "w");
  1738.    
  1739.     fputc(song.fps, fp);
  1740.     fputc(song.repeat, fp);
  1741.     fputc(song.instrumentCount, fp);
  1742.     fputc(song.orderCount, fp);
  1743.    
  1744.     int i;
  1745.     for(i = 0; i < song.instrumentCount; i++)
  1746.     {
  1747.         Instrument instrument = song.instruments[i];
  1748.         int a;
  1749.         for(a = 0; a < 8; a++)
  1750.         {
  1751.             Effect effect = instrument.effects[a];
  1752.             fputc(effect.enable, fp);
  1753.             fputc(effect.effect, fp);
  1754.             fputc(effect.argument, fp);
  1755.         }
  1756.     }
  1757.    
  1758.     for(i = 0; i < song.orderCount; i++)
  1759.     {
  1760.         Order order = song.orders[i];
  1761.         int a;
  1762.         for(a = 0; a < 32; a++)
  1763.         {
  1764.             Frame frame = order.frames[a];
  1765.             int b;
  1766.             for(b = 0; b < 4; b++)
  1767.             {
  1768.                 Entry entry = frame.entries[b];
  1769.                 fputc(entry.noteCommand.note, fp);
  1770.                 fputc(entry.noteCommand.octave, fp);
  1771.                 fputc(entry.noteCommand.volume, fp);
  1772.                 fputc(entry.noteCommand.applyInstrument, fp);
  1773.                 fputc(entry.noteCommand.instrument, fp);
  1774.                 fputc(entry.effect.enable, fp);
  1775.                 fputc(entry.effect.effect, fp);
  1776.                 fputc(entry.effect.argument, fp);
  1777.             }
  1778.         }
  1779.     }
  1780.    
  1781.     fclose(fp);
  1782. }
  1783.  
  1784. void load()
  1785. {
  1786.     FILE *fp;
  1787.     fp = fopen("chiptune.sav", "r");
  1788.    
  1789.     song.fps = fgetc(fp);
  1790.     song.repeat = fgetc(fp);
  1791.     song.instrumentCount = fgetc(fp);
  1792.     song.orderCount = fgetc(fp);
  1793.    
  1794.     int i;
  1795.     for(i = 0; i < song.instrumentCount; i++)
  1796.     {
  1797.         int a;
  1798.         for(a = 0; a < 8; a++)
  1799.         {
  1800.             song.instruments[i].effects[a].enable = fgetc(fp);
  1801.             song.instruments[i].effects[a].effect = fgetc(fp);
  1802.             song.instruments[i].effects[a].argument = fgetc(fp);
  1803.         }
  1804.     }
  1805.    
  1806.     for(i = 0; i < song.orderCount; i++)
  1807.     {
  1808.         int a;
  1809.         for(a = 0; a < 32; a++)
  1810.         {
  1811.             int b;
  1812.             for(b = 0; b < 4; b++)
  1813.             {
  1814.                 song.orders[i].frames[a].entries[b].noteCommand.note = fgetc(fp);
  1815.                 song.orders[i].frames[a].entries[b].noteCommand.octave = fgetc(fp);
  1816.                 song.orders[i].frames[a].entries[b].noteCommand.volume = fgetc(fp);
  1817.                 song.orders[i].frames[a].entries[b].noteCommand.applyInstrument = fgetc(fp);
  1818.                 song.orders[i].frames[a].entries[b].noteCommand.instrument = fgetc(fp);
  1819.                 song.orders[i].frames[a].entries[b].effect.enable = fgetc(fp);
  1820.                 song.orders[i].frames[a].entries[b].effect.effect = fgetc(fp);
  1821.                 song.orders[i].frames[a].entries[b].effect.argument = fgetc(fp);
  1822.             }
  1823.         }
  1824.     }
  1825.    
  1826.     fclose(fp);
  1827.    
  1828.     curOrder = 0;
  1829.     curInstrument = 0;
  1830.     curEffect = 0;
  1831.     curFrame = 0;
  1832.     orderScroll = 0;
  1833.     instrumentScroll = 0;
  1834.     trackerScroll = 0;
  1835.    
  1836.     drawWindows();
  1837.     drawStatus();
  1838. }
  1839.  
  1840. void inputLoop()
  1841. {
  1842.     quietFrame = newQuietFrame();
  1843.     int e = 1;
  1844.     while(e)
  1845.     {
  1846.         int c = getch();
  1847.         switch(c)
  1848.         {
  1849.             case KEY_F(5):
  1850.                 reset();
  1851.                 break;
  1852.             case KEY_F(6):
  1853.                 playNote(NOTE_C, 3, 0xFF, 0);
  1854.                 playNote(NOTE_E, 4, 0xFF, 1);
  1855.                 playNote(NOTE_G, 3, 0xFF, 2);
  1856.                 playNote(NOTE_Bb, 4, 0xFF, 3);
  1857.                 break;
  1858.             case KEY_F(7):
  1859.                 playCurrentFrame();
  1860.                 break;
  1861.             case KEY_F(8):
  1862.                 playCurrentOrder();
  1863.                 break;
  1864.             case KEY_F(9):
  1865.                 save();
  1866.             case KEY_F(10):
  1867.                 load();
  1868.                 break;
  1869.             case 'q':
  1870.                 e = 0;
  1871.                 break;
  1872.             case KEY_RESIZE:
  1873.                 initWindows();
  1874.                 break;
  1875.             case '.':
  1876.                 curOctave = (curOctave + 1) % 8;
  1877.                 drawStatus();
  1878.                 break;
  1879.             case ',':
  1880.                 if(curOctave == 0)
  1881.                 {
  1882.                     curOctave = 7;
  1883.                 }
  1884.                 else
  1885.                 {
  1886.                     curOctave--;
  1887.                 }
  1888.                 drawStatus();
  1889.                 break;
  1890.             case '\'':
  1891.                 song.fps = (song.fps + 1) % 25;
  1892.                 if(song.fps <= 0) song.fps = 1;
  1893.                 drawStatus();
  1894.                 break;
  1895.             case ';':
  1896.                 if(song.fps <= 1)
  1897.                 {
  1898.                     song.fps = 24;
  1899.                 }
  1900.                 else
  1901.                 {
  1902.                     song.fps--;
  1903.                 }
  1904.                 drawStatus();
  1905.                 break;
  1906.             case '\n':
  1907.                 if(curMode == MODE_PLAY)
  1908.                 {
  1909.                     editMode();
  1910.                 }
  1911.                 else
  1912.                 {
  1913.                     playMode();
  1914.                 }
  1915.                 break;
  1916.             case ' ':
  1917.                 if(curMode == MODE_JAM)
  1918.                 {
  1919.                     editMode();
  1920.                 }
  1921.                 else
  1922.                 {
  1923.                     jamMode();
  1924.                 }
  1925.                 break;
  1926.             case ERR:
  1927.                 break;
  1928.             default:
  1929.                 switch(curMode)
  1930.                 {
  1931.                     case MODE_EDIT:
  1932.                         editInput(c);
  1933.                         break;
  1934.                     case MODE_PLAY:
  1935.                         playInput(c);
  1936.                         break;
  1937.                     case MODE_JAM:
  1938.                         jamInput(c);
  1939.                         break;
  1940.                 }
  1941.         }
  1942.     }
  1943. }
  1944.  
  1945. void gui()
  1946. {
  1947.     initscr();
  1948.     clear();
  1949.     noecho();
  1950.     cbreak();
  1951.     keypad(stdscr, TRUE);
  1952.     nodelay(stdscr, TRUE);
  1953.     refresh();
  1954.    
  1955.     initWindows();
  1956.     inputLoop();
  1957.    
  1958.     endwin();
  1959. }
  1960.  
  1961. void initSong()
  1962. {
  1963.     song.fps = 8;
  1964.     song.repeat = 0;
  1965.     song.orderCount = 1;
  1966.     song.instrumentCount = 1;
  1967.    
  1968.     Order orders[MAX_ORDERS];
  1969.     song.orders = orders;
  1970.    
  1971.     Instrument instruments[MAX_INSTRUMENTS];
  1972.     song.instruments = instruments;
  1973. }
  1974.  
  1975. int main(int argc, char *argv[])
  1976. {
  1977.     if(argc > 1)
  1978.     {
  1979.         strcpy(serialPort, argv[1]);
  1980.     }
  1981.     else
  1982.     {
  1983.         printf("Enter full path to serial device: ");
  1984.         scanf("%s", serialPort);
  1985.     }
  1986.    
  1987.     if(out = fopen(serialPort, "w"))
  1988.     {
  1989.         initSong();
  1990.         reset();
  1991.         gui();
  1992.         reset();
  1993.         fclose(out);
  1994.     }
  1995.     else
  1996.     {
  1997.         printf("Unable to open file!\n");
  1998.         exit(1);
  1999.     }
  2000.    
  2001.     return 0;
  2002. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement