#include #include #include #include #include #include #include #include #include #include #include "trakker.h" #include "trakker_version.h" #define SAMPLERATE 48000 #define BUFFER_SIZE 250000 static std::string note_name[] = { "C ", "C#", "D ", "D#", "E ", "F ", "F#", "G ", "G#", "A ", "A#", "B " }; static std::string pages[] = { "1. Info", "2. Pattern", "3. Scope", "4. Piano Roll", "5. Config", "6. Help" }; static char* device = "default"; char* file; bool colorMode = 0; // 0 - Auto, 1 - Monochrome, 2 - 8-bit, 3 - Full int mtype = XMP_MODE_AUTO; int smix = 70; int display = 0; int mode = 0; int vol; int hMin = 0; int hMax = 2048; int hOffset = 0; int vMin = 0; int vMax = 2048; int vOffset = 0; int looped = 0; int prMin = 255; int prMax = 0; bool stopped; bool loop; bool ptnChans = true; bool dynamicRoll = true; bool ptnOrder = true; std::map efxtable; std::map efxmemtable; int main(int argc, char *argv[]) { printf("TRAKKER %s (using XMP %s)\n", TRAKKER_VERSION, xmp_version); for (int a = 1; a < argc; ++a) { if (strcmp(argv[a], "-h") == 0) { printf("\n"); printf("Help\n"); printf("-h Show this message.\n"); printf("-d Start on the specified panel.\n"); printf("-c Force terminal color mode.\n"); printf(" 0 Auto (default)\n"); printf(" 1 Monochrome\n"); printf(" 2 8bit\n"); printf(" 3 Full\n"); printf("-s Stereo Seperation\n"); exit(0); } else if (strcmp(argv[a], "-d") == 0) { int newdisplay = atoi(argv[a+1])-1; if (newdisplay > 5 || newdisplay < 0) fprintf(stderr, "Display argument is invalid.\n"); else { printf("Setting display to \"%s\"\n", pages[newdisplay].c_str()); display = newdisplay; } a++; } else if (strcmp(argv[a], "-c") == 0) { colorMode = atoi(argv[a+1]); a++; } else if (strcmp(argv[a], "-s") == 0) { int newmix = atoi(argv[a+1]); if (newmix > 100 || newmix < 0) fprintf(stderr, "Stero seperation argument is invalid.\n"); else { printf("Setting Stero seperation to %i%%\n", newmix); smix = newmix; } a++; } else if (strcmp(argv[a], "-t") == 0) { char* newmode = argv[a+1]; if (strcmp(newmode, "mod") == 0) { mtype = XMP_MODE_MOD; } else if (strcmp(newmode, "noisetracker") == 0) { mtype = XMP_MODE_NOISETRACKER; } else if (strcmp(newmode, "protracker") == 0) { mtype = XMP_MODE_PROTRACKER; } else if (strcmp(newmode, "s3m") == 0) { mtype = XMP_MODE_S3M; } else if (strcmp(newmode, "st3") == 0) { mtype = XMP_MODE_ST3; } else if (strcmp(newmode, "st3gus") == 0) { mtype = XMP_MODE_ST3GUS; } else if (strcmp(newmode, "xm") == 0) { mtype = XMP_MODE_XM; } else if (strcmp(newmode, "ft2") == 0) { mtype = XMP_MODE_FT2; } else if (strcmp(newmode, "it") == 0) { mtype = XMP_MODE_IT; } else if (strcmp(newmode, "itsmp") == 0) { mtype = XMP_MODE_ITSMP; } a++; } else if (!file) { file = argv[a]; } else { fprintf(stderr, "Unknown argument: %s\n", argv[a]); exit(EXIT_FAILURE); } } int err; if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf(stderr, "Playback open error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } if ((err = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16, SND_PCM_ACCESS_RW_INTERLEAVED, 2, SAMPLERATE, 1, BUFFER_SIZE)) < 0) { fprintf(stderr, "Playback open error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } printf("%s initialized.\n", "ALSA"); xc = xmp_create_context(); if (xmp_load_module(xc, file) != 0) { fprintf(stderr, "Failed to load Module: %s\n", file); exit(EXIT_FAILURE); } else printf("Loaded Module: \"%s\"\n", file); struct xmp_module_info xmi; struct xmp_frame_info xfi; initscr(); start_color(); if ((has_colors() == TRUE && colorMode == 0) || colorMode >= 2) { if ((can_change_color() == TRUE && colorMode == 0) || colorMode == 3) { // Primary Background init_pair(1, COLOR_BLACK, 8); // Inactive Section init_pair(2, 8, 7); // Active Section init_pair(3, 0, 12); // Display init_pair(4, 7, COLOR_BLACK); // Display Row# init_pair(5, 3, COLOR_BLACK); // Display Playhead init_pair(6, COLOR_WHITE, COLOR_BLUE); // Display Playhead Row# init_pair(7, COLOR_YELLOW, COLOR_BLUE); // Display Stopped Playhead init_pair(8, COLOR_WHITE, COLOR_RED); // Display Stopped Playhead Row# init_pair(9, COLOR_YELLOW, COLOR_RED); // Display VU Bar Low init_pair(10, COLOR_WHITE, COLOR_GREEN); // Display VU Bar Medium init_pair(11, COLOR_WHITE, COLOR_YELLOW); // Display VU Bar High init_pair(12, COLOR_WHITE, COLOR_RED); // Inverted Text init_pair(13, COLOR_WHITE, COLOR_BLACK); } else { // Primary Background init_pair(1, COLOR_BLACK, 8); // Inactive Section init_pair(2, COLOR_BLACK, COLOR_WHITE); // Active Section init_pair(3, COLOR_BLACK, COLOR_CYAN); // Display init_pair(4, COLOR_WHITE, COLOR_BLACK); // Display Row# init_pair(5, COLOR_YELLOW, COLOR_BLACK); // Display Playhead init_pair(6, COLOR_WHITE, COLOR_BLUE); // Display Playhead Row# init_pair(7, COLOR_YELLOW, COLOR_BLUE); // Display Stopped Playhead init_pair(8, COLOR_WHITE, COLOR_RED); // Display Stopped Playhead Row# init_pair(9, COLOR_YELLOW, COLOR_RED); // Display VU Bar Low init_pair(10, COLOR_WHITE, COLOR_GREEN); // Display VU Bar Medium init_pair(11, COLOR_WHITE, COLOR_YELLOW); // Display VU Bar High init_pair(12, COLOR_WHITE, COLOR_RED); // Inverted Text init_pair(13, COLOR_WHITE, COLOR_BLACK); } } else { // Primary Background init_pair(1, COLOR_BLACK, COLOR_BLACK); // Inactive Section init_pair(2, COLOR_WHITE, COLOR_BLACK); // Active Section init_pair(3, COLOR_BLACK, COLOR_WHITE); // Display init_pair(4, COLOR_WHITE, COLOR_BLACK); // Display Row# init_pair(5, COLOR_WHITE, COLOR_BLACK); // Display Playhead init_pair(6, COLOR_BLACK, COLOR_WHITE); // Display Playhead Row# init_pair(7, COLOR_BLACK, COLOR_WHITE); // Display Stopped Playhead init_pair(8, COLOR_WHITE, COLOR_BLACK); // Display Stopped Playhead Row# init_pair(9, COLOR_WHITE, COLOR_BLACK); // Display VU Bar Low init_pair(10, COLOR_WHITE, COLOR_WHITE); // Display VU Bar Medium init_pair(11, COLOR_WHITE, COLOR_WHITE); // Display VU Bar High init_pair(12, COLOR_WHITE, COLOR_WHITE); // Inverted Text init_pair(13, COLOR_WHITE, COLOR_BLACK); } cbreak(); noecho(); curs_set(0); bkgd(COLOR_PAIR(1)); refresh(); createWindows(); keypad(stdscr, TRUE); int row, pos; xmp_get_module_info(xc, &xmi); row = pos = -1; generateEffectsTable(xmi.mod->type); xmp_set_player(xc, XMP_PLAYER_MODE, mtype); xmp_start_player(xc, SAMPLERATE, 0); xmp_set_player(xc, XMP_PLAYER_MIX, smix); int key; bool displayChanged; displayChanged = true; while (true) { xmp_get_frame_info(xc, &xfi); if (xmp_play_frame(xc) != 0 && !stopped) break; if (xfi.loop_count > looped && !loop) break; else looped = xfi.loop_count; keys: timeout(stopped?-1:0); if ((key = getch()) != 0) { vol = xmp_get_player(xc, XMP_PLAYER_VOLUME); switch (key) { case KEY_RESIZE: destroyWindows(); createWindows(); displayChanged = true; // Update top section. break; case 'q': goto end; break; case KEY_LEFT: case 'a': // Move Channels Left if (hOffset > hMin) hOffset-=1; break; case KEY_RIGHT: case 'd': // Move Channels Right if (hOffset < hMax) hOffset+=1; break; case KEY_UP: case 'w': // Seek Up if (vOffset > vMin) vOffset-=1; break; case KEY_DOWN: case 's': // Seek Down if (vOffset < vMax) vOffset+=1; break; case 'A': // Move Channels Left (faster) if (hOffset > hMin) hOffset-=5; break; case 'D': // Move Channels Right (faster) if (hOffset < hMax) hOffset+=5; break; case 'W': // Seek Up (faster) if (vOffset > vMin) vOffset-=5; break; case 'S': // Seek Down (faster) if (vOffset < vMax) vOffset+=5; break; case KEY_PPAGE: if (vOffset > vMin + LINES-6) vOffset-=(LINES-5); else vOffset = vMin; break; case KEY_NPAGE: if (vOffset < vMax - LINES-6) vOffset+=(LINES-5); else vOffset = vMax; break; case 10: case ' ': // Pause/Play xfi.time-=20; stopped = !stopped; break; case '+': case '=': if (vol < 200) xmp_set_player(xc, XMP_PLAYER_VOLUME, vol+=5); break; case '-': if (vol > 0) xmp_set_player(xc, XMP_PLAYER_VOLUME, vol-=5); break; case '[': if (smix > 0) smix-=5; xmp_set_player(xc, XMP_PLAYER_MIX, smix); break; case ']': if (smix < 100) smix+=5; xmp_set_player(xc, XMP_PLAYER_MIX, smix); break; case 'l': loop = !loop; break; case '1': case '2': case '3': case '4': case '5': case '6': display = key-49; displayChanged = true; break; case 27: // ALT if ((key = getch()) != 0) { switch (key) { case '1': ptnChans = !ptnChans; break; case '2': prMin = 255; prMax = 0; dynamicRoll = !dynamicRoll; break; case '3': ptnOrder = !ptnOrder; break; } } break; case 'R': hOffset = vOffset = 0; break; }; displayHeader(&xmi, &xfi); } if (displayChanged) { werase(dis); werase(tab); hOffset = 0; vOffset = 0; move(0, 0); for (int d = 0; d < sizeof(pages)/sizeof(*pages); d++) { printw(" "); chtype tpair; if (display == d) tpair = COLOR_PAIR(3); else tpair = COLOR_PAIR(2); attron(tpair); printw(" "); printw(pages[d].c_str()); printw(" "); attroff(tpair); printw(" "); } mode = 0; wmove(tab, 0, 0); displayChanged = false; } if (!stopped) { if (xfi.pos != pos) { pos = xfi.pos; row = -1; } if (xfi.row != row) { row = xfi.row; displayHeader(&xmi, &xfi); } wrefresh(tab); wrefresh(dis); frames = snd_pcm_bytes_to_frames(handle, xfi.buffer_size); if (snd_pcm_writei(handle, xfi.buffer, frames) < 0) { snd_pcm_prepare(handle); } } else goto keys; } end: clrtoeol(); refresh(); endwin(); xmp_end_player(xc); xmp_release_module(xc); xmp_free_context(xc); if ((err = snd_pcm_drain(handle)) < 0) { printf("snd_pcm_drain failed: %s\n", snd_strerror(err)); } snd_pcm_close(handle); printf("Goodbye!\n"); return 0; } void destroyWindows() { delwin(tab); delwin(dis); } void createWindows() { tab = newwin(LINES-1, COLS, 1, 0); wmove(tab, 0, 0); wprintw(tab, ""); wbkgd(tab, COLOR_PAIR(3)); wrefresh(tab); dis = newwin(LINES-4, COLS-2, 3, 1); wmove(dis, 0, 0); wprintw(dis, ""); wbkgd(dis, COLOR_PAIR(4)); wrefresh(dis); } void displayHeader(xmp_module_info *mi, xmp_frame_info *fi) { werase(dis); wclrtoeol(tab); mvwaddstr(tab, 0, 1, mi->mod->name); mvwprintw( tab, 0, COLS-12, "%02u:%02u/%02u:%02u", ((fi->time / 1000) / 60) % 60, (fi->time / 1000) % 60, ((fi->total_time / 1000) / 60) % 60, (fi->total_time / 1000) % 60 ); wmove(tab, 1, 0); wclrtoeol(tab); mvwprintw(tab, 1, COLS-10, "VOL: %i%%", vol); mvwprintw(tab, 1, 1, "%i/%ibpm", fi->speed, fi->bpm); mvwprintw(tab, LINES-2, 1, "%s", stopped?"STOPPED":"PLAYING"); if (display == 0) { displayInfo(mi, fi); } else if (display == 1) { displayPatterns(mi, fi); } else if (display == 2) { displayScope(mi, fi); } else if (display == 3) { displayNoteRoll(mi, fi); } else if (display == 4) { displayPlayer(); } else { displayHelp(); } refresh(); wrefresh(dis); wrefresh(tab); } void displayInfo(xmp_module_info *mi, xmp_frame_info *fi) { wattron(dis, A_BOLD); mvwaddstr(dis, 1-vOffset, 1, "Format:"); mvwaddstr(dis, 2-vOffset, 1, "Channels:"); mvwaddstr(dis, 4-vOffset, 1, "Instruments:"); mvwaddstr(dis, (6+mi->mod->ins)-vOffset, 1, "Samples:"); wattroff(dis, A_BOLD); mvwprintw(dis, 1-vOffset, 16, mi->mod->type); mvwprintw(dis, 2-vOffset, 16, "%i", mi->mod->chn); mvwprintw(dis, 4-vOffset, 16, "%i", mi->mod->ins); mvwprintw(dis, (6+mi->mod->ins)-vOffset, 16, "%i", mi->mod->smp); for (int xi = 0; xi < mi->mod->ins; xi++) { mvwprintw(dis, xi+5-vOffset, 1, "[%02X] %s", xi, mi->mod->xxi[xi].name); } for (int xs = 0; xs < mi->mod->smp; xs++) { mvwprintw(dis, xs+(7+mi->mod->ins)-vOffset, 1, "[%02X] %s", xs, mi->mod->xxs[xs].name); } } void displayPatterns(xmp_module_info *mi, xmp_frame_info *fi) { int chnsize = 15; if (ptnOrder) { for (int j = 0; j < mi->mod->len; j++) { if (mi->mod->xxo[j] == 0xFF) continue; chtype patpair = (j == fi->pos)?COLOR_PAIR(6):COLOR_PAIR(4); wattron(dis, patpair); mvwprintw(dis, LINES-5, (COLS/2)+(j*3)-(fi->pos*3)-3, "%02X", mi->mod->xxo[j]); wattroff(dis, patpair); } } wattroff(tab, COLOR_PAIR(5)); for (int y = 0; y < LINES - (5-(!ptnOrder)); y++) { if (ptnChans && y == 0) { chtype chnvw = COLOR_PAIR(5); chtype vollo = COLOR_PAIR(10); chtype volmd = COLOR_PAIR(11); chtype volhi = COLOR_PAIR(12); int cxpos = 3; wmove(dis, 0, cxpos); for (int i = 0; i < mi->mod->chn; i++) { struct xmp_channel_info cinfo = fi->channel_info[i]; int voll = (cinfo.volume * (256-cinfo.pan)/256); if (voll >= 48) wattron(dis, volhi); mvwaddch(dis, 0, (cxpos++)-hOffset, ' '); wattroff(dis, volhi); if (voll >= 32) wattron(dis, volmd); mvwaddch(dis, 0, (cxpos++)-hOffset, ' '); wattroff(dis, volmd); if (voll >= 16) wattron(dis, vollo); mvwaddch(dis, 0, (cxpos++)-hOffset, ' '); wattroff(dis, vollo); if (voll >= 8) wattron(dis, vollo); mvwaddch(dis, 0, (cxpos++)-hOffset, ' '); wattroff(dis, vollo); if (voll > 0) wattron(dis, vollo); mvwaddch(dis, 0, (cxpos++)-hOffset, ' '); wattroff(dis, vollo); wattron(dis, chnvw); mvwaddch(dis, 0, (cxpos++)-hOffset, ' '); char *cbuf = new char[2]; sprintf(cbuf, "%02X", i); mvwaddch(dis, 0, (cxpos++)-hOffset, cbuf[0]); mvwaddch(dis, 0, (cxpos++)-hOffset, cbuf[1]); free(cbuf); mvwaddch(dis, 0, (cxpos++)-hOffset, ' '); wattroff(dis, chnvw); int volr = (cinfo.volume * cinfo.pan/256); if (volr > 0) wattron(dis, vollo); mvwaddch(dis, 0, (cxpos++)-hOffset, ' '); wattroff(dis, vollo); if (volr >= 8) wattron(dis, vollo); mvwaddch(dis, 0, (cxpos++)-hOffset, ' '); wattroff(dis, vollo); if (volr >= 16) wattron(dis, vollo); mvwaddch(dis, 0, (cxpos++)-hOffset, ' '); wattroff(dis, vollo); if (volr >= 32) wattron(dis, volmd); mvwaddch(dis, 0, (cxpos++)-hOffset, ' '); wattroff(dis, volmd); if (volr >= 48) wattron(dis, volhi); mvwaddch(dis, 0, (cxpos++)-hOffset, ' '); wattroff(dis, volhi); mvwaddch(dis, 0, (cxpos++)-hOffset, ' '); } continue; } int trow = (fi->row - ((LINES - 2) / 2))+y; if (trow > fi->num_rows-1 || trow < 0) { continue; } chtype numpair = COLOR_PAIR((trow==fi->row)?(stopped?9:7):5); chtype rowpair = COLOR_PAIR((trow==fi->row)?(stopped?8:6):4); if (trow == fi->row) wattron(dis, A_BOLD); wmove(dis, y, 0); wattron(dis, numpair); wprintw(dis, "%02X", trow); wattroff(dis, numpair); wattron(dis, rowpair); for (int i = 0; i < mi->mod->chn+1; i++) { if (i >= mi->mod->chn) { mvwaddch(dis, y, ((i*chnsize)+2)-hOffset, '|'); break; } int track = mi->mod->xxp[fi->pattern]->index[i]; struct xmp_event event = mi->mod->xxt[track]->event[trow]; char *lnbuf = new char[chnsize+1]; char *note = new char[4]; char *ins = new char[3]; char *vol = new char[4]; char *efx = new char[4]; if (event.note > 0x80) snprintf(note, 4, "==="); else if (event.note > 0) snprintf(note, 4, "%s%d", note_name[event.note % 12].c_str(), event.note / 12); else snprintf(note, 4, "..."); if (event.ins > 0) snprintf(ins, 3, "%02X", event.ins); else snprintf(ins, 3, ".."); if (event.vol != 0) snprintf(vol, 4, "v%02X", event.vol-1); else if (event.note > 0 && event.note <= 0x80) snprintf(vol, 4, "v40"); else snprintf(vol, 4, "..."); char f1; if ((efxmemtable[event.fxt] || event.fxp != 0) && (f1 = efxtable[event.fxt]) != NULL) snprintf(efx, 4, "%c%02X", f1, event.fxp); else snprintf(efx, 4, "..."); sprintf(lnbuf, "|%s %s %s %s", note, ins, vol, efx); for (int z = 0; z < chnsize; z++) { if (((i*chnsize)+2+z)-hOffset < 2) continue; mvwaddch(dis, y, ((i*chnsize)+2+z)-hOffset, lnbuf[z]); } free(lnbuf); free(note); free(ins); free(vol); free(efx); } wattroff(dis, rowpair); if (trow == fi->row) wattroff(dis, A_BOLD); } } int lerp (int a, int b, float f) { return a + f * (b - a); } #include std::vector bufbuf; void displayScope(xmp_module_info *mi, xmp_frame_info *fi) { bufbuf.resize(fi->buffer_size); const char* xbuf = (char*)fi->buffer; float nxcol = 0; int rate = 2; int midLine = (LINES-4)/2; int horzInc = 1; for (int s = 0; s < fi->buffer_size; s++) { if (nxcol >= COLS-2) break; int l = lerp(bufbuf[s], xbuf[s], 0.2f); int newpos = ((l+0x80) * (LINES - 4)) / 0xFF; horzInc = (newpos < midLine)?-1:1; for (int j = midLine; j != newpos; j+=horzInc) { wmove(dis, j, (int)nxcol); waddch(dis, '|'); } nxcol+=(1.0*(COLS-2)/fi->buffer_size); bufbuf[s] = l; } } void displayNoteRoll(xmp_module_info *mi, xmp_frame_info *fi) { int ins = mi->mod->ins; chtype no_pair = COLOR_PAIR(5); if (dynamicRoll) { for (int l = 1; l <= 8; l++) { int cnote = (l*12); if (cnote <= prMin && l == (prMin / 12)) { wmove(dis, 0, 0); wprintw(dis, "<%i", l); } else if (cnote < prMax && cnote > prMin) { wmove(dis, 0, (((cnote - prMin) * (COLS - 5)) / (prMax - prMin))+3); wprintw(dis, "%i", l); } } } for (int y = vOffset; y < ins; y++) { if (!dynamicRoll) { prMin = 0; prMax = 144; } if (y > (LINES - (5+dynamicRoll))+vOffset || y < 0) continue; wmove(dis, (y-vOffset)+dynamicRoll, 0); wattron(dis, no_pair); wprintw(dis, "%02X", y+1); wattroff(dis, no_pair); wclrtoeol(dis); for (int c = 0; c < mi->mod->chn; c++) { struct xmp_channel_info cinfo = fi->channel_info[c]; if (dynamicRoll) { if (cinfo.note < prMin) prMin = cinfo.note-1; else if (cinfo.note > prMax && cinfo.note != 255) prMax = cinfo.note+1; } int note = ((cinfo.note - prMin) * (COLS - 5)) / (dynamicRoll?(prMax - prMin):96); if (cinfo.instrument != y) continue; wmove(dis, (y-vOffset)+dynamicRoll, note+3); if (cinfo.volume >= 32) waddstr(dis, "#"); else if (cinfo.volume >= 16 && (char)mvwinch(dis, (y-vOffset)+dynamicRoll, note+3) != '#') waddstr(dis, "="); else if (cinfo.volume > 0 && ((char)mvwinch(dis, (y-vOffset)+dynamicRoll, note+3) != '-' || (char)mvwinch(dis, (y-vOffset)+dynamicRoll, note+3) != '#')) waddstr(dis, "-"); } wmove(dis, y, COLS-4); } } void displayPlayer() { wattron(dis, A_BOLD); mvwaddstr(dis, 1-vOffset, 1, "Loop"); mvwaddstr(dis, 2-vOffset, 1, "Stereo Seperation"); mvwaddstr(dis, 3-vOffset, 1, "Color Mode"); mvwaddstr(dis, 5-vOffset, 1, "1. Pattern Channels"); mvwaddstr(dis, 6-vOffset, 1, "2. Dynamic Note Roll"); mvwaddstr(dis, 7-vOffset, 1, "3. Pattern Order"); wattroff(dis, A_BOLD); mvwaddstr(dis, 1-vOffset, 20, loop?"[ #] YES":"[# ] NO"); mvwprintw(dis, 2-vOffset, 20, "%i%%", smix); mvwprintw(dis, 3-vOffset, 20, "%i", colorMode); mvwaddstr(dis, 5-vOffset, 22, ptnChans?"[ #] YES":"[# ] NO"); mvwaddstr(dis, 6-vOffset, 22, dynamicRoll?"[ #] YES":"[# ] NO"); mvwaddstr(dis, 7-vOffset, 22, ptnOrder?"[ #] YES":"[# ] NO"); } void displayHelp() { wattron(dis, A_BOLD); mvwaddstr(dis, 1-vOffset, 2, " / ######## TRAKKER"); mvwaddstr(dis, 2-vOffset, 2, " / // / libxmp"); mvwaddstr(dis, 3-vOffset, 2, "/ // / "); mvwaddstr(dis, 4-vOffset, 2, " // / by Nick G. (Wirlaburla)"); mvwaddstr(dis, 5-vOffset, 2, " // / Licensed under the GPLv3"); mvwaddstr(dis, 7-vOffset, 1, "Play/Pause........"); mvwaddstr(dis, 8-vOffset, 1, "Switch Tabs......."); mvwaddstr(dis, 9-vOffset, 1, "Fast Shift........"); mvwaddstr(dis, 10-vOffset, 1, "Horizontal Shift.."); mvwaddstr(dis, 11-vOffset, 1, "Vertical Shift...."); mvwaddstr(dis, 12-vOffset, 1, "Volume............"); mvwaddstr(dis, 13-vOffset, 1, "Refresh..........."); mvwaddstr(dis, 14-vOffset, 1, "Vertical Scroll..."); mvwaddstr(dis, 15-vOffset, 1, "Stero Seperation.."); mvwaddstr(dis, 16-vOffset, 1, "Option Toggle....."); wattroff(dis, A_BOLD); mvwaddstr(dis, 1-vOffset, 25, TRAKKER_VERSION); mvwaddstr(dis, 2-vOffset, 25, xmp_version); mvwaddstr(dis, 7-vOffset, 20, "Space"); mvwaddstr(dis, 8-vOffset, 20, "Tab"); mvwaddstr(dis, 9-vOffset, 20, "Shift + W A S D"); mvwaddstr(dis, 10-vOffset, 20, "Left Arrow / Right Arrow OR A / D"); mvwaddstr(dis, 11-vOffset, 20, "Up Arrow / Down Arrow OR W / S"); mvwaddstr(dis, 12-vOffset, 20, "+ / -"); mvwaddstr(dis, 13-vOffset, 20, "R"); mvwaddstr(dis, 14-vOffset, 20, "Page-Up / Page-Down"); mvwaddstr(dis, 15-vOffset, 20, "[ / ]"); mvwaddstr(dis, 16-vOffset, 20, "Alt + 0-9"); } void generateEffectsTable(char* type) { if (isPartOf(type, "669")) { addToEffects(96, 'A', true); addToEffects(97, 'B', true); addToEffects(98, 'C', true); addToEffects(99, 'D', true); addToEffects(100, 'E', true); addToEffects(126, 'F', true); } else if (isPartOf(type, "Farandole")) { addToEffects(249, '1', true); addToEffects(248, '2', true); addToEffects(122, '3', true); addToEffects(251, '4', true); addToEffects(254, '5', true); addToEffects(4, '6', true); addToEffects(256, '7', true); addToEffects(252, '8', true); addToEffects(123, '9', true); addToEffects(250, 'C', true); addToEffects(15, 'F', true); } else if (isPartOf(type, "Imago Orpheus")) { addToEffects(1, '1', true); addToEffects(2, '2', true); addToEffects(3, '3', true); addToEffects(4, '4', true); addToEffects(5, '5', true); addToEffects(6, '6', true); addToEffects(7, '7', true); addToEffects(8, '8', true); addToEffects(9, '9', true); addToEffects(10, 'A', true); addToEffects(11, 'B', true); addToEffects(12, 'C', true); addToEffects(13, 'D', true); addToEffects(14, 'E', true); addToEffects(15, 'F', true); addToEffects(16, 'G', true); addToEffects(17, 'H', true); addToEffects(18, 'I', true); addToEffects(19, 'J', true); addToEffects(20, 'K', true); addToEffects(21, 'L', true); addToEffects(22, 'M', true); addToEffects(23, 'N', true); addToEffects(24, 'O', true); addToEffects(25, 'P', true); addToEffects(26, 'Q', true); addToEffects(27, 'R', true); addToEffects(28, 'S', true); addToEffects(29, 'T', true); addToEffects(30, 'U', true); addToEffects(31, 'V', true); addToEffects(32, 'W', true); addToEffects(33, 'X', true); addToEffects(34, 'Y', true); addToEffects(35, 'Z', true); } else if (isPartOf(type, "S3M")) { addToEffects(163, 'A', false); addToEffects(11, 'B', true); addToEffects(13, 'C', true); addToEffects(10, 'D', true); addToEffects(2, 'E', true); addToEffects(1, 'F', true); addToEffects(3, 'G', true); addToEffects(4, 'H', true); addToEffects(29, 'I', true); addToEffects(180, 'J', true); addToEffects(6, 'K', true); addToEffects(5, 'L', true); addToEffects(9, 'O', true); addToEffects(27, 'Q', true); addToEffects(7, 'R', true); addToEffects(254, 'S', true); addToEffects(171, 'T', false); addToEffects(172, 'U', true); addToEffects(16, 'V', true); addToEffects(8, 'X', true); addToEffects(141, 'X', true); addToEffects(14, 'S', true); } else if (isPartOf(type, "IT")) { addToEffects(163, 'A', false); addToEffects(11, 'B', true); addToEffects(142, 'C', true); addToEffects(10, 'D', true); addToEffects(2, 'E', true); addToEffects(1, 'F', true); addToEffects(3, 'G', true); addToEffects(4, 'H', true); addToEffects(29, 'I', true); addToEffects(180, 'J', true); addToEffects(6, 'K', true); addToEffects(5, 'L', true); addToEffects(128, 'M', true); addToEffects(129, 'N', true); addToEffects(9, 'O', false); // OpenMPT doc states this should be true but there is zero effect at 00 (0*256=0) addToEffects(137, 'P', true); addToEffects(27, 'Q', true); addToEffects(7, 'R', true); addToEffects(254, 'S', true); addToEffects(135, 'T', false); addToEffects(172, 'U', true); addToEffects(16, 'V', true); addToEffects(17, 'W', true); addToEffects(8, 'X', true); addToEffects(138, 'Y', true); addToEffects(141, 'S', true); addToEffects(136, 'S', true); addToEffects(14, 'S', true); addToEffects(192, 'c', true); addToEffects(193, 'd', true); addToEffects(194, 'a', true); addToEffects(195, 'b', true); addToEffects(132, 'S', true); addToEffects(139, 'S', true); addToEffects(140, 'S', true); } else if (isPartOf(type, "LIQ")) { addToEffects(0, 'A', true); addToEffects(171, 'B', true); addToEffects(13, 'C', true); addToEffects(2, 'D', true); addToEffects(172, 'F', true); addToEffects(11, 'J', true); addToEffects(10, 'L', true); addToEffects(14, 'M', true); addToEffects(3, 'N', true); addToEffects(9, 'O', true); addToEffects(163, 'S', true); addToEffects(7, 'T', true); addToEffects(1, 'U', true); addToEffects(4, 'V', true); addToEffects(5, 'X', true); addToEffects(6, 'Y', true); } else if (isPartOf(type, "Oktalyzer")) { addToEffects(1, '1', true); addToEffects(2, '2', true); addToEffects(112, '0', true); addToEffects(113, '0', true); addToEffects(114, '0', true); addToEffects(115, '6', true); addToEffects(116, '5', true); addToEffects(156, '6', true); addToEffects(11, 'B', true); addToEffects(15, 'F', true); addToEffects(157, '5', true); addToEffects(12, 'C', true); addToEffects(10, 'A', true); addToEffects(174, 'E', true); addToEffects(17, 'E', true); addToEffects(0, '0', true); } else if (isPartOf(type, "STX")) { addToEffects(15, 'A', true); addToEffects(11, 'B', true); addToEffects(13, 'C', true); addToEffects(10, 'D', true); addToEffects(2, 'E', true); addToEffects(1, 'F', true); addToEffects(3, 'G', true); addToEffects(4, 'H', true); addToEffects(29, 'I', true); addToEffects(0, 'J', true); } else if (isPartOf(type, "Funk")) { addToEffects(121, 'A', true); addToEffects(120, 'B', true); addToEffects(122, 'C', true); addToEffects(123, 'D', true); addToEffects(124, 'G', true); addToEffects(125, 'H', true); addToEffects(0, 'L', true); addToEffects(12, 'N', true); addToEffects(127, 'O', true); addToEffects(14, 'O', true); addToEffects(15, 'O', true); } else { addToEffects(0, '0', false); addToEffects(1, '1', false); addToEffects(2, '2', false); addToEffects(3, '3', true); addToEffects(4, '4', true); addToEffects(5, '5', false); addToEffects(6, '6', false); addToEffects(7, '7', true); addToEffects(8, '8', true); addToEffects(9, '9', true); addToEffects(10, 'A', false); addToEffects(11, 'B', true); addToEffects(12, 'C', true); addToEffects(13, 'D', true); addToEffects(14, 'E', false); addToEffects(15, 'F', true); addToEffects(16, 'G', true); addToEffects(27, 'Q', true); addToEffects(181, 'P', true); addToEffects(17, 'H', true); addToEffects(21, 'L', true); addToEffects(164, 'c', true); addToEffects(33, 'X', true); addToEffects(20, 'K', true); addToEffects(25, 'P', true); addToEffects(29, 'T', true); addToEffects(146, '4', true); addToEffects(160, 'x', true); addToEffects(161, 'x', true); addToEffects(171, 'F', true); } } // We do not care for previous effects (memory = true) because it's a tracker. // 'mem' is only for discarding zero values. void addToEffects(int id, char efx, bool mem) { efxtable[id] = efx; efxmemtable[id] = mem; } bool isPartOf(char* w1, char* w2) { int i=0; int j=0; while(w1[i]!='\0'){ if(w1[i] == w2[j]) { int init = i; while (w1[i] == w2[j] && w2[j]!='\0') { j++; i++; } if(w2[j]=='\0') { return true; } j=0; } i++; } return false; }