View difference between Paste ID: sW0WrMWw and yRX9GW4U
SHOW: | | - or go back to the newest paste.
1-
// Backup #2
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-
		//applyInstrument goes here
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-
		mvwprintw(orderWindow, i + 1 - orderScroll, 1, "%c 0x%x: ", song.repeat == i ? '*' : '-', i);
607+
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-
	for(i = -2; i <= 32 && i < h2 - 4; i++)
740+
741
	wclear(trackerWindow);
742
	wattrset(trackerWindow, A_NORMAL);
743-
		if(i >= 0 && i < 32)
743+
744
	wattron(trackerWindow, A_BOLD);
745
	box(trackerWindow, 0, 0);
746-
			mvwprintw(trackerWindow, i + 3, 1, "0x%x%x ", (i & 0xF0) >> 4, i & 0xF);
746+
747
	printTitle(trackerWindow, "Tracker");
748-
		else if(i == -2)
748+
749
	
750-
			mvwprintw(trackerWindow, i + 3, 1, "(0x%x)", curOrder);
750+
751
	for(i = -2 + trackerScroll; i <= 32 && i < h2 - 4 + trackerScroll; i++)
752-
		else if(i == -1 || i == 32)
752+
753
		wattrset(trackerWindow, A_BOLD);
754
		if(i - trackerScroll >= 0 && i - trackerScroll < 32)
755-
			wmove(trackerWindow, i + 3, 1);
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-
			if(i == -2)
768+
769
			{
770
				waddch(trackerWindow, ACS_HLINE);
771
			}
772-
				mvwprintw(trackerWindow, i + 3, a * 10 + 7, "Osc #%i   ", a + 1);
772+
773
		wattrset(trackerWindow, A_NORMAL);
774
		waddch(trackerWindow, ACS_VLINE);
775-
			else if(i == -1 || i == 32)
775+
776
		int a;
777-
				wmove(trackerWindow, i + 3, a * 10 + 7);
777+
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-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "---");
791+
792
					waddch(trackerWindow, ACS_HLINE);
793
				}
794-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "RES");
794+
795
			else
796
			{
797-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "+++");
797+
798
				wattrset(trackerWindow, curFrame == i && curOsc == a && curCol == 0 ? A_REVERSE : A_NORMAL);
799
				switch(entry.noteCommand.note)
800-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "xxx");
800+
801
					case 0x0:
802
						mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "---");
803-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "C-%x", entry.noteCommand.octave);
803+
804
					case 0x1:
805
						mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "RES");
806-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "C#%x", entry.noteCommand.octave);
806+
807
					case 0x2:
808
						mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "+++");
809-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "D-%x", entry.noteCommand.octave);
809+
810
					case 0x3:
811
						mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "xxx");
812-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "D#%x", entry.noteCommand.octave);
812+
813
					case 0x4:
814
						mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "C-%x", entry.noteCommand.octave);
815-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "E-%x", entry.noteCommand.octave);
815+
816
					case 0x5:
817
						mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "C#%x", entry.noteCommand.octave);
818-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "F-%x", entry.noteCommand.octave);
818+
819
					case 0x6:
820
						mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "D-%x", entry.noteCommand.octave);
821-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "F#%x", entry.noteCommand.octave);
821+
822
					case 0x7:
823
						mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "D#%x", entry.noteCommand.octave);
824-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "G-%x", entry.noteCommand.octave);
824+
825
					case 0x8:
826
						mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "E-%x", entry.noteCommand.octave);
827-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "G#%x", entry.noteCommand.octave);
827+
828
					case 0x9:
829
						mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "F-%x", entry.noteCommand.octave);
830-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "A-%x", entry.noteCommand.octave);
830+
831
					case 0xA:
832
						mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "F#%x", entry.noteCommand.octave);
833-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "A#%x", entry.noteCommand.octave);
833+
834
					case 0xB:
835
						mvwprintw(trackerWindow, i + 3 - trackerScroll, a * 10 + 7, "G-%x", entry.noteCommand.octave);
836-
						mvwprintw(trackerWindow, i + 3, a * 10 + 7, "B-%x", entry.noteCommand.octave);
836+
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-
		placeCursor();
888+
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-
	mvprintw(LINES - 1, 0, "MODE: %s | SPEED: %i FPS | REPEAT: 0x%x | ORDERS: %i | INSTRUMENTS: %i", modeString, song.fps, song.repeat, song.orderCount, song.instrumentCount);
931+
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-
							curFrame = (curFrame + 1) % 32;
1183+
1184
						case KEY_F(4):
1185
							curOsc = 3;
1186
							drawTrackerWindow();
1187-
							curFrame--;
1187+
1188-
							if(curFrame < 0) curFrame = 31;
1188+
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
}