From ca6e7067a87fc01f7a71a3223e61dd821410c306 Mon Sep 17 00:00:00 2001 From: Leandro Nini Date: Sat, 4 Jul 2026 21:14:53 +0200 Subject: [PATCH 01/15] Apply changes from fork https://github.com/jansalleine/gt2fork/commit/67350a43bed2db5930c74e5952fdc691e5939776 https://github.com/jansalleine/gt2fork/commit/418c5fa33387b1b25eadcf4c49176a69f84a861b https://github.com/jansalleine/gt2fork/commit/307b004620d8561ed613e13522feed1fc5fef034 https://github.com/jansalleine/gt2fork/commit/b752523fb4f4277e07dc099cdc23fd5b7553821c https://github.com/jansalleine/gt2fork/commit/c0caad1554dfda19fee315f8b0e7f4f5ecaebaba https://github.com/jansalleine/gt2fork/commit/21afc95e459b95c1500550d183b723459a4419b2 --- src/gconsole.c | 24 ++++++++ src/gconsole.h | 28 ++++++++- src/gdisplay.c | 154 +++++++++++++++++++++++++------------------------ src/gfile.c | 30 +++++----- src/ghelp.c | 76 ++++++++++++------------ src/goattrk2.c | 149 ++++++++++++++++++++++++++++++----------------- src/goattrk2.h | 7 ++- src/gpattern.c | 2 +- 8 files changed, 284 insertions(+), 186 deletions(-) diff --git a/src/gconsole.c b/src/gconsole.c index b1c3cb9..f28c0d0 100644 --- a/src/gconsole.c +++ b/src/gconsole.c @@ -33,6 +33,28 @@ int mousesizex = 11; int mousesizey = 20; unsigned bigwindow = 1; +POSITIONS dpos = +{ + MAX_COLUMNS-21, // channelsX + MAX_ROWS-2, // channelsY + 80, // instrumentsX + 10, // instrumentsY + 64, // loadboxX + 2, // loadboxY + 1, // octaveX + MAX_ROWS-2, // octaveY + 54, // orderlistX + 2, // orderlistY + 14, // patternsX + 2, // patternsY + ((MAX_COLUMNS/2) - 30), // statusBottomX + MAX_ROWS-2, // statusBottomY + MAX_COLUMNS-1, // statusTopEndX + 80, // statusTopFvX + 0, // statusTopX + 0 // statusTopY +}; + void loadexternalpalette(void); void initicon(void); @@ -52,6 +74,8 @@ int initscreen(void) unsigned xsize = MAX_COLUMNS * 8; unsigned ysize = MAX_ROWS * 16; + printf("xsize: %d, ysize: %d", xsize, ysize); + if (bigwindow > 1) { fontwidth *= bigwindow; diff --git a/src/gconsole.h b/src/gconsole.h index d185d49..804be6d 100644 --- a/src/gconsole.h +++ b/src/gconsole.h @@ -1,11 +1,34 @@ #ifndef GCONSOLE_H #define GCONSOLE_H -#define MAX_COLUMNS 100 -#define MAX_ROWS 37 +#define MAX_COLUMNS 128 +#define MAX_ROWS 40 #define HOLDDELAY 24 #define DOUBLECLICKDELAY 15 +typedef struct +{ + int channelsX; + int channelsY; + int instrumentsX; + int instrumentsY; + int loadboxX; + int loadboxY; + int octaveX; + int octaveY; + int orderlistX; + int orderlistY; + int patternsX; + int patternsY; + int statusBottomX; + int statusBottomY; + int statusTopEndX; + int statusTopFvX; + int statusTopX; + int statusTopY; +} POSITIONS; + + int initscreen(void); void closescreen(void); void clearscreen(void); @@ -25,6 +48,7 @@ extern int mouseb, prevmouseb; extern int mouseheld; extern int mousex, mousey; extern unsigned bigwindow; +extern POSITIONS dpos; #endif #endif diff --git a/src/gdisplay.c b/src/gdisplay.c index 19fb44b..0ba2ed9 100644 --- a/src/gdisplay.c +++ b/src/gdisplay.c @@ -75,43 +75,43 @@ void printstatus(void) else sprintf(textbuffer, "%s - %s", programname, loadedsongfilename); textbuffer[49] = 0; - printtext(0, 0, colors.CHEADER, textbuffer); + printtext(dpos.statusTopX+1, dpos.statusTopY, colors.CHEADER, textbuffer); if (usefinevib) - printtext(40+10, 0, colors.CHEADER, "FV"); + printtext(dpos.statusTopFvX, dpos.statusTopY, colors.CHEADER, "FV"); if (optimizepulse) - printtext(43+10, 0, colors.CHEADER, "PO"); + printtext(dpos.statusTopFvX+3, dpos.statusTopY, colors.CHEADER, "PO"); if (optimizerealtime) - printtext(46+10, 0, colors.CHEADER, "RO"); + printtext(dpos.statusTopFvX+6, dpos.statusTopY, colors.CHEADER, "RO"); if (ntsc) - printtext(49+10, 0, colors.CHEADER, "NTSC"); + printtext(dpos.statusTopFvX+9, dpos.statusTopY, colors.CHEADER, "NTSC"); else - printtext(49+10, 0, colors.CHEADER, " PAL"); + printtext(dpos.statusTopFvX+9, dpos.statusTopY, colors.CHEADER, " PAL"); if (!sidmodel) - printtext(54+10, 0, colors.CHEADER, "6581"); + printtext(dpos.statusTopFvX+14, dpos.statusTopY, colors.CHEADER, "6581"); else - printtext(54+10, 0, colors.CHEADER, "8580"); + printtext(dpos.statusTopFvX+14, dpos.statusTopY, colors.CHEADER, "8580"); sprintf(textbuffer, "HR:%04X", adparam); - printtext(59+10, 0, colors.CHEADER, textbuffer); - if (eamode) printbg(62+10+eacolumn, 0, cc, 1); + printtext(dpos.statusTopFvX+19, dpos.statusTopY, colors.CHEADER, textbuffer); + if (eamode) printbg(dpos.statusTopFvX+22+eacolumn, dpos.statusTopY, cc, 1); if (multiplier) { sprintf(textbuffer, "%2dX", multiplier); - printtext(67+10, 0, colors.CHEADER, textbuffer); + printtext(dpos.statusTopFvX+27, dpos.statusTopY, colors.CHEADER, textbuffer); } - else printtext(67+10, 0, colors.CHEADER, "25Hz"); + else printtext(dpos.statusTopFvX+27, dpos.statusTopY, colors.CHEADER, "25Hz"); - printtext(72+20, 0, colors.CHEADER, "F12=HELP"); + printtext(dpos.statusTopEndX-8, dpos.statusTopY, colors.CHEADER, "F12=HELP"); } else { - printtext(0, 0, colors.CHEADER, " PLAY | PLAYPOS | PLAYPATT | STOP | LOAD | SAVE | PACK/RL | HELP | CLEAR | QUIT |"); + printtext(0, dpos.statusTopY, colors.CHEADER, " PLAY | PLAYPOS | PLAYPATT | STOP | LOAD | SAVE | PACK/RL | HELP | CLEAR | QUIT |"); } if ((followplay) && (isplaying())) @@ -141,9 +141,9 @@ void printstatus(void) { esview = newpos; } - if (newpos - esview >= VISIBLEORDERLIST) + if (newpos - esview >= VISIBLEORDERLISTMONO) { - esview = newpos - VISIBLEORDERLIST + 1; + esview = newpos - VISIBLEORDERLISTMONO + 1; } } } @@ -151,8 +151,14 @@ void printstatus(void) for (c = 0; c < MAX_CHN; c++) { - sprintf(textbuffer, "CHN %d PATT.%02X", c+1, epnum[c]); - printtext(2+c*15, 2, colors.CTITLE, textbuffer); + sprintf(textbuffer, "CH."); + printtext(dpos.patternsX+c*13, dpos.patternsY, colors.CTITLE, textbuffer); + sprintf(textbuffer, "%d", c+1); + printtext(dpos.patternsX+3+c*13, dpos.patternsY, colors.CTITLE, textbuffer); + sprintf(textbuffer, "PATT."); + printtext(dpos.patternsX+5+c*13, dpos.patternsY, colors.CTITLE, textbuffer); + sprintf(textbuffer, "%02X", epnum[c]); + printtext(dpos.patternsX+10+c*13, dpos.patternsY, colors.CTITLE, textbuffer); for (d = 0; d < VISIBLEPATTROWS; d++) { @@ -207,31 +213,31 @@ void printstatus(void) textbuffer[3] = 0; if (p%stepsize) { - printtext(2+c*15, 3+d, colors.CNORMAL, textbuffer); + printtext(dpos.patternsX+c*13, dpos.patternsY+1+d, colors.CNORMAL, textbuffer); } else { - printtext(2+c*15, 3+d, colors.CCOMMAND, textbuffer); + printtext(dpos.patternsX+c*13, dpos.patternsY+1+d, colors.CCOMMAND, textbuffer); } if (color == colors.CNORMAL) color2 = colors.CCOMMAND; else color2 = color; - printtext(6+c*15, 3+d, color2, &textbuffer[4]); - printtext(10+c*15, 3+d, color, &textbuffer[8]); - printtext(12+c*15, 3+d, color2, &textbuffer[10]); - printtext(13+c*15, 3+d, color, &textbuffer[11]); + printtext(dpos.patternsX+3+c*13, dpos.patternsY+1+d, color2, &textbuffer[4]); + printtext(dpos.patternsX+7+c*13, dpos.patternsY+1+d, color, &textbuffer[8]); + printtext(dpos.patternsX+9+c*13, dpos.patternsY+1+d, color2, &textbuffer[10]); + printtext(dpos.patternsX+10+c*13, dpos.patternsY+1+d, color, &textbuffer[11]); if (c == epmarkchn) { if (epmarkstart <= epmarkend) { if ((p >= epmarkstart) && (p <= epmarkend)) - printbg(2+c*15+4, 3+d, 8, 9); + printbg(dpos.patternsX+c*13+3, dpos.patternsY+1+d, 8, 9); } else { if ((p <= epmarkstart) && (p >= epmarkend)) - printbg(2+c*15+4, 3+d, 8, 9); + printbg(dpos.patternsX+c*13+3, dpos.patternsY+1+d, 8, 9); } } if ((color == colors.CEDIT) && (editmode == EDIT_PATTERN) && (epchn == c)) @@ -239,11 +245,11 @@ void printstatus(void) switch(epcolumn) { case 0: - if (!eamode) printbg(2+c*15+4, 3+d, cc, 3); + if (!eamode) printbg(dpos.patternsX+c*13+3, dpos.patternsY+1+d, cc, 3); break; default: - if (!eamode) printbg(2+c*15+7+epcolumn, 3+d, cc, 1); + if (!eamode) printbg(dpos.patternsX+c*13+6+epcolumn, dpos.patternsY+1+d, cc, 1); break; } } @@ -251,12 +257,12 @@ void printstatus(void) } sprintf(textbuffer, "CHN ORDERLIST (SUBTUNE %02X, POS %02X)", esnum, eseditpos); - printtext(40+10, 2, colors.CTITLE, textbuffer); + printtext(dpos.orderlistX, dpos.orderlistY, colors.CTITLE, textbuffer); for (c = 0; c < MAX_CHN; c++) { sprintf(textbuffer, " %d ", c+1); - printtext(40+10, 3+c, colors.CTITLE, textbuffer); - for (d = 0; d < VISIBLEORDERLIST; d++) + printtext(dpos.orderlistX, dpos.orderlistY+1+c, colors.CTITLE, textbuffer); + for (d = 0; d < VISIBLEORDERLISTMONO; d++) { int p = esview+d; color = colors.CNORMAL; @@ -311,7 +317,7 @@ void printstatus(void) if (color == colors.CNORMAL) color = colors.CCOMMAND; } } - printtext(44+10+d*3, 3+c, color, textbuffer); + printtext(dpos.orderlistX+4+d*3, dpos.orderlistY+1+c, color, textbuffer); if (c == esmarkchn) { if (esmarkstart <= esmarkend) @@ -319,9 +325,9 @@ void printstatus(void) if ((p >= esmarkstart) && (p <= esmarkend)) { if (p != esmarkend) - printbg(44+10+d*3, 3+c, 1, 3); + printbg(dpos.orderlistX+4+d*3, dpos.orderlistY+1+c, 1, 3); else - printbg(44+10+d*3, 3+c, 1, 2); + printbg(dpos.orderlistX+4+d*3, dpos.orderlistY+1+c, 1, 2); } } else @@ -329,72 +335,72 @@ void printstatus(void) if ((p <= esmarkstart) && (p >= esmarkend)) { if (p != esmarkstart) - printbg(44+10+d*3, 3+c, 1, 3); + printbg(dpos.orderlistX+4+d*3, dpos.orderlistY+1+c, 1, 3); else - printbg(44+10+d*3, 3+c, 1, 2); + printbg(dpos.orderlistX+4+d*3, dpos.orderlistY+1+c, 1, 2); } } } if ((p == eseditpos) && (editmode == EDIT_ORDERLIST) && (eschn == c)) { - if (!eamode) printbg(44+10+d*3+escolumn, 3+c, cc, 1); + if (!eamode) printbg(dpos.orderlistX+4+d*3+escolumn, dpos.orderlistY+1+c, cc, 1); } } } sprintf(textbuffer, "INSTRUMENT NUM. %02X %-16s", einum, instr[einum].name); - printtext(40+10, 7, colors.CTITLE, textbuffer); + printtext(dpos.instrumentsX, dpos.instrumentsY, colors.CTITLE, textbuffer); sprintf(textbuffer, "Attack/Decay %02X", instr[einum].ad); if (eipos == 0) color = colors.CEDIT; else color = colors.CNORMAL; - printtext(40+10, 8, color, textbuffer); + printtext(dpos.instrumentsX, dpos.instrumentsY+1, color, textbuffer); sprintf(textbuffer, "Sustain/Release %02X", instr[einum].sr); if (eipos == 1) color = colors.CEDIT; else color = colors.CNORMAL; - printtext(40+10, 9, color, textbuffer); + printtext(dpos.instrumentsX, dpos.instrumentsY+2, color, textbuffer); sprintf(textbuffer, "Wavetable Pos %02X", instr[einum].ptr[WTBL]); if (eipos == 2) color = colors.CEDIT; else color = colors.CNORMAL; - printtext(40+10, 10, color, textbuffer); + printtext(dpos.instrumentsX, dpos.instrumentsY+3, color, textbuffer); sprintf(textbuffer, "Pulsetable Pos %02X", instr[einum].ptr[PTBL]); if (eipos == 3) color = colors.CEDIT; else color = colors.CNORMAL; - printtext(40+10, 11, color, textbuffer); + printtext(dpos.instrumentsX, dpos.instrumentsY+4, color, textbuffer); sprintf(textbuffer, "Filtertable Pos %02X", instr[einum].ptr[FTBL]); if (eipos == 4) color = colors.CEDIT; else color = colors.CNORMAL; - printtext(40+10, 12, color, textbuffer); + printtext(dpos.instrumentsX, dpos.instrumentsY+5, color, textbuffer); sprintf(textbuffer, "Vibrato Param %02X", instr[einum].ptr[STBL]); if (eipos == 5) color = colors.CEDIT; else color = colors.CNORMAL; - printtext(60+10, 8, color, textbuffer); + printtext(dpos.instrumentsX+20, dpos.instrumentsY+1, color, textbuffer); sprintf(textbuffer, "Vibrato Delay %02X", instr[einum].vibdelay); if (eipos == 6) color = colors.CEDIT; else color = colors.CNORMAL; - printtext(60+10, 9, color, textbuffer); + printtext(dpos.instrumentsX+20, dpos.instrumentsY+2, color, textbuffer); sprintf(textbuffer, "HR/Gate Timer %02X", instr[einum].gatetimer); if (eipos == 7) color = colors.CEDIT; else color = colors.CNORMAL; - printtext(60+10, 10, color, textbuffer); + printtext(dpos.instrumentsX+20, dpos.instrumentsY+3, color, textbuffer); sprintf(textbuffer, "1stFrame Wave %02X", instr[einum].firstwave); if (eipos == 8) color = colors.CEDIT; else color = colors.CNORMAL; - printtext(60+10, 11, color, textbuffer); + printtext(dpos.instrumentsX+20, dpos.instrumentsY+4, color, textbuffer); if (editmode == EDIT_INSTRUMENT) { if (eipos < 9) { - if (!eamode) printbg(56+10+eicolumn+20*(eipos/5), 8+(eipos%5), cc, 1); + if (!eamode) printbg(dpos.instrumentsX+16+eicolumn+20*(eipos/5), dpos.instrumentsY+1+(eipos%5), cc, 1); } else { - if (!eamode) printbg(60+10+strlen(instr[einum].name), 7, cc, 1); + if (!eamode) printbg(dpos.instrumentsX+20+strlen(instr[einum].name), dpos.instrumentsY, cc, 1); } } sprintf(textbuffer, "WAVE TBL PULSETBL FILT.TBL SPEEDTBL"); - printtext(40+10, 14, colors.CTITLE, textbuffer); + printtext(dpos.instrumentsX, dpos.instrumentsY+7, colors.CTITLE, textbuffer); for (c = 0; c < MAX_TABLES; c++) { @@ -427,19 +433,19 @@ void printstatus(void) memset(&textbuffer[6], '.', 2); } } - printtext(40+10+10*c, 15+d, color, textbuffer); + printtext(dpos.instrumentsX+10*c, dpos.instrumentsY+8+d, color, textbuffer); if (etmarknum == c) { if (etmarkstart <= etmarkend) { if ((p >= etmarkstart) && (p <= etmarkend)) - printbg(40+10+10*c+3, 15+d, 1, 5); + printbg(dpos.instrumentsX+10*c+3, dpos.instrumentsY+8+d, 1, 5); } else { if ((p <= etmarkstart) && (p >= etmarkend)) - printbg(40+10+10*c+3, 15+d, 1, 5); + printbg(dpos.instrumentsX+10*c+3, dpos.instrumentsY+8+d, 1, 5); } } } @@ -447,38 +453,38 @@ void printstatus(void) if (editmode == EDIT_TABLES) { - if (!eamode) printbg(43+10+etnum*10+(etcolumn & 1)+(etcolumn/2)*3, 15+etpos-etview[etnum], cc, 1); + if (!eamode) printbg(dpos.instrumentsX+3+etnum*10+(etcolumn & 1)+(etcolumn/2)*3, dpos.instrumentsY+8+etpos-etview[etnum], cc, 1); } - printtext(40+10, 31, colors.CTITLE, "NAME "); + printtext(dpos.instrumentsX, dpos.instrumentsY+8+VISIBLETABLEROWS+1, colors.CTITLE, "NAME "); sprintf(textbuffer, "%-32s", songname); - printtext(49+10, 31, colors.CEDIT, textbuffer); + printtext(dpos.instrumentsX+9, dpos.instrumentsY+8+VISIBLETABLEROWS+1, colors.CEDIT, textbuffer); - printtext(40+10, 32, colors.CTITLE, "AUTHOR "); + printtext(dpos.instrumentsX, dpos.instrumentsY+8+VISIBLETABLEROWS+2, colors.CTITLE, "AUTHOR "); sprintf(textbuffer, "%-32s", authorname); - printtext(49+10, 32, colors.CEDIT, textbuffer); + printtext(dpos.instrumentsX+9, dpos.instrumentsY+8+VISIBLETABLEROWS+2, colors.CEDIT, textbuffer); - printtext(40+10, 33, colors.CTITLE, "RELEASED "); + printtext(dpos.instrumentsX, dpos.instrumentsY+8+VISIBLETABLEROWS+3, colors.CTITLE, "RELEASED "); sprintf(textbuffer, "%-32s", copyrightname); - printtext(49+10, 33, colors.CEDIT, textbuffer); + printtext(dpos.instrumentsX+9, dpos.instrumentsY+8+VISIBLETABLEROWS+3, colors.CEDIT, textbuffer); if ((editmode == EDIT_NAMES) && (!eamode)) { switch(enpos) { case 0: - printbg(49+10+strlen(songname), 31, cc, 1); + printbg(dpos.instrumentsX+9+strlen(songname), dpos.instrumentsY+8+VISIBLETABLEROWS+1, cc, 1); break; case 1: - printbg(49+10+strlen(authorname), 32, cc, 1); + printbg(dpos.instrumentsX+9+strlen(authorname), dpos.instrumentsY+8+VISIBLETABLEROWS+2, cc, 1); break; case 2: - printbg(49+10+strlen(copyrightname), 33, cc, 1); + printbg(dpos.instrumentsX+9+strlen(copyrightname), dpos.instrumentsY+8+VISIBLETABLEROWS+3, cc, 1); break; } } sprintf(textbuffer, "OCTAVE %d", epoctave); - printtext(0, 35, colors.CTITLE, textbuffer); + printtext(dpos.octaveX, dpos.octaveY, colors.CTITLE, textbuffer); switch(autoadvance) { @@ -495,11 +501,11 @@ void printstatus(void) break; } - if (recordmode) printtext(0, 36, color, "EDITMODE"); - else printtext(0, 36, color, "JAM MODE"); + if (recordmode) printtext(dpos.octaveX, dpos.octaveY+1, color, "EDITMODE"); + else printtext(dpos.octaveX, dpos.octaveY+1, color, "JAM MODE"); - if (isplaying()) printtext(10, 35, colors.CTITLE, "PLAYING"); - else printtext(10, 35, colors.CTITLE, "STOPPED"); + if (isplaying()) printtext(dpos.octaveX+10, dpos.octaveY, colors.CTITLE, "PLAYING"); + else printtext(dpos.octaveX+10, dpos.octaveY, colors.CTITLE, "STOPPED"); if (multiplier) { if (!ntsc) @@ -515,9 +521,9 @@ void printstatus(void) sprintf(textbuffer, " %02d%c%02d ", timemin, timechar[(timeframe/15) & 1], timesec); } - printtext(10, 36, colors.CEDIT, textbuffer); + printtext(dpos.octaveX+10, dpos.octaveY+1, colors.CEDIT, textbuffer); - printtext(80, 35, colors.CTITLE, " CHN1 CHN2 CHN3 "); + printtext(dpos.channelsX, dpos.channelsY, colors.CTITLE, " CHN1 CHN2 CHN3 "); for (c = 0; c < MAX_CHN; c++) { int chnpos = chn[c].songptr; @@ -527,13 +533,13 @@ void printstatus(void) if (chnrow > pattlen[chn[c].pattnum]) chnrow = pattlen[chn[c].pattnum]; if (chnrow >= 100) chnrow -= 100; - sprintf(textbuffer, "%03d/%02d", + sprintf(textbuffer, "%03X/%02X", chnpos,chnrow); - printtext(80+7*c, 36, colors.CEDIT, textbuffer); + printtext(dpos.channelsX+7*c, dpos.channelsY+1, colors.CEDIT, textbuffer); } - if (etlock) printtext(78, 36, colors.CTITLE, " "); - else printtext(78, 36, colors.CTITLE, "U"); + if (etlock) printtext(dpos.channelsX-2, dpos.channelsY+1, colors.CTITLE, " "); + else printtext(dpos.channelsX-2, dpos.channelsY+1, colors.CTITLE, "U"); } diff --git a/src/gfile.c b/src/gfile.c index 9ab63bb..d54fb3c 100644 --- a/src/gfile.c +++ b/src/gfile.c @@ -412,11 +412,11 @@ int fileselector(char *name, char *path, char *filter, char *title, int filemode if (isplaying()) printstatus(); for (c = 0; c < VISIBLEFILES+7; c++) { - printblank(50-(MAX_FILENAME+10)/2, 3+c, MAX_FILENAME+10); + printblank(dpos.loadboxX-(MAX_FILENAME+10)/2, dpos.loadboxY+c, MAX_FILENAME+10); } - drawbox(50-(MAX_FILENAME+10)/2, 3, 15, MAX_FILENAME+10, VISIBLEFILES+7); - printblankc(50-(MAX_FILENAME+10)/2+1, 4, colors.CHEADER, MAX_FILENAME+8); - printtext(50-(MAX_FILENAME+10)/2+1, 4, colors.CHEADER, title); + drawbox(dpos.loadboxX-(MAX_FILENAME+10)/2, dpos.loadboxY, 15, MAX_FILENAME+10, VISIBLEFILES+7); + printblankc(dpos.loadboxX-(MAX_FILENAME+10)/2+1, dpos.loadboxY+1, colors.CHEADER, MAX_FILENAME+8); + printtext(dpos.loadboxX-(MAX_FILENAME+10)/2+1, dpos.loadboxY+1, colors.CHEADER, title); for (c = 0; c < VISIBLEFILES; c++) { @@ -444,30 +444,30 @@ int fileselector(char *name, char *path, char *filter, char *title, int filemode color = colors.CNORMAL; if ((fileview+c) == filepos) color = colors.CEDIT; textbuffer[68] = 0; - printtext(50-(MAX_FILENAME+10)/2+1, 5+c, color, textbuffer); - if ((!filemode) && ((fileview+c) == filepos)) printbg(50-(MAX_FILENAME+10)/2+1, 5+c, cc, 68); + printtext(dpos.loadboxX-(MAX_FILENAME+10)/2+1, dpos.loadboxY+2+c, color, textbuffer); + if ((!filemode) && ((fileview+c) == filepos)) printbg(dpos.loadboxX-(MAX_FILENAME+10)/2+1, dpos.loadboxY+2+c, cc, 68); } - printtext(50-(MAX_FILENAME+10)/2+1, 6+VISIBLEFILES, 15, "PATH: "); + printtext(dpos.loadboxX-(MAX_FILENAME+10)/2+1, dpos.loadboxY+3+VISIBLEFILES, 15, "PATH: "); sprintf(textbuffer, "%-60s", path); textbuffer[MAX_FILENAME] = 0; color = (filemode == 1) ? colors.CEDIT : colors.CNORMAL; - printtext(50-(MAX_FILENAME+10)/2+9, 6+VISIBLEFILES, color, textbuffer); - if ((filemode == 1) && (strlen(path) < MAX_FILENAME)) printbg(50-(MAX_FILENAME+10)/2+9+strlen(path), 6+VISIBLEFILES, cc, 1); + printtext(dpos.loadboxX-(MAX_FILENAME+10)/2+9, dpos.loadboxY+3+VISIBLEFILES, color, textbuffer); + if ((filemode == 1) && (strlen(path) < MAX_FILENAME)) printbg(dpos.loadboxX-(MAX_FILENAME+10)/2+9+strlen(path), dpos.loadboxY+3+VISIBLEFILES, cc, 1); - printtext(50-(MAX_FILENAME+10)/2+1, 7+VISIBLEFILES, 15, "FILTER: "); + printtext(dpos.loadboxX-(MAX_FILENAME+10)/2+1, dpos.loadboxY+4+VISIBLEFILES, 15, "FILTER: "); sprintf(textbuffer, "%-60s", filter); textbuffer[MAX_FILENAME] = 0; color = (filemode == 2) ? colors.CEDIT : colors.CNORMAL; - printtext(50-(MAX_FILENAME+10)/2+9, 7+VISIBLEFILES, color, textbuffer); - if (filemode == 2) printbg(50-(MAX_FILENAME+10)/2+9+strlen(filter), 7+VISIBLEFILES, cc, 1); + printtext(dpos.loadboxX-(MAX_FILENAME+10)/2+9, dpos.loadboxY+4+VISIBLEFILES, color, textbuffer); + if (filemode == 2) printbg(dpos.loadboxX-(MAX_FILENAME+10)/2+9+strlen(filter), dpos.loadboxY+4+VISIBLEFILES, cc, 1); - printtext(50-(MAX_FILENAME+10)/2+1, 8+VISIBLEFILES, 15, "NAME: "); + printtext(dpos.loadboxX-(MAX_FILENAME+10)/2+1, dpos.loadboxY+5+VISIBLEFILES, 15, "NAME: "); sprintf(textbuffer, "%-60s", name); textbuffer[MAX_FILENAME] = 0; color = (filemode == 3) ? colors.CEDIT : colors.CNORMAL; - printtext(50-(MAX_FILENAME+10)/2+9, 8+VISIBLEFILES, color, textbuffer); - if (filemode == 3) printbg(50-(MAX_FILENAME+10)/2+9+strlen(name), 8+VISIBLEFILES, cc, 1); + printtext(dpos.loadboxX-(MAX_FILENAME+10)/2+9, dpos.loadboxY+5+VISIBLEFILES, color, textbuffer); + if (filemode == 3) printbg(dpos.loadboxX-(MAX_FILENAME+10)/2+9+strlen(name), dpos.loadboxY+5+VISIBLEFILES, cc, 1); if (win_quitted) exitfilesel = 0; diff --git a/src/ghelp.c b/src/ghelp.c index 67a17b7..72928e8 100644 --- a/src/ghelp.c +++ b/src/ghelp.c @@ -242,7 +242,9 @@ void onlinehelp(int standalone,int context) int hview = -1; - int lastrow=0; + int lastrow = 0; + + const int offsetX = 24; unsigned char color_header = HELP_HEADER; unsigned char color_normal = HELP_NORMAL; @@ -259,70 +261,70 @@ void onlinehelp(int standalone,int context) clearscreen(); if(!context) { - printtext(0, left++, color_header, "GENERAL KEYS"); - left = printrows(0,left,color_normal, genkeys); + printtext(0 + offsetX, left++, color_header, "GENERAL KEYS"); + left = printrows(0 + offsetX,left,color_normal, genkeys); left++; - printtext(40,right++, color_header, "PATTERN EDIT MODE"); - right = printrows(40,right,color_normal, patternkeys); + printtext(40 + offsetX,right++, color_header, "PATTERN EDIT MODE"); + right = printrows(40 + offsetX,right,color_normal, patternkeys); right++; - - printtext(0, left++, color_header, "SONG EDIT MODE"); - left = printrows(0,left,color_normal, songkeys); + + printtext(0 + offsetX, left++, color_header, "SONG EDIT MODE"); + left = printrows(0 + offsetX,left,color_normal, songkeys); left++; - printtext(0, left++, color_header, "SONGNAME EDIT MODE"); - printtext(0, left++, color_normal, "Use cursor UP/DOWN to change rows"); + printtext(0 + offsetX, left++, color_header, "SONGNAME EDIT MODE"); + printtext(0 + offsetX, left++, color_normal, "Use cursor UP/DOWN to change rows"); left++; - printtext(40,right++, color_header, "INSTRUMENT/TABLE EDIT MODE"); - right = printrows(40,right,color_normal, instkeys); + printtext(40 + offsetX,right++, color_header, "INSTRUMENT/TABLE EDIT MODE"); + right = printrows(40 + offsetX,right,color_normal, instkeys); right++; - + left = (left= 13 + c*15) && (mousex <= 14 + c*15)) + if ((mousey == dpos.patternsY) && + (mousex >= dpos.patternsX + 11 + c*13) && + (mousex <= dpos.patternsX + 12 + c*13)) { if ((!prevmouseb) || (mouseheld > HOLDDELAY)) { @@ -701,10 +703,13 @@ void mousecommands(void) } else { - if ((mousey >= 2) && (mousey <= 34) && (mousex >= 6 + c*15) && (mousex <= 14 + c*15)) + if ((mousey >= dpos.patternsY) && + (mousey <= dpos.statusBottomY - 1) && + (mousex >= dpos.patternsX + 3 + c*13) && + (mousex <= dpos.patternsX + 12 + c*13)) { - int x = mousex-6-c*15; - int newpos = mousey-3+epview; + int x = mousex-(dpos.patternsX + 3)-c*13; + int newpos = mousey-(dpos.patternsY+1)+epview; if (newpos < 0) newpos = 0; if (newpos > pattlen[epnum[epchn]]) newpos = pattlen[epnum[epchn]]; @@ -735,8 +740,8 @@ void mousecommands(void) { if (mouseb & MOUSEB_LEFT) { - if (mousey == 2) eppos--; - if (mousey == 34) eppos++; + if (mousey == dpos.patternsY) eppos--; + if (mousey == dpos.statusBottomY - 1) eppos++; } } if (eppos < 0) eppos = 0; @@ -748,10 +753,12 @@ void mousecommands(void) } // Song editpos & songnumber selection - if ((mousey >= 3) && (mousey <= 8) && (mousex >= 40+10)) + if ((mousey >= dpos.orderlistY) && + (mousey <= dpos.orderlistY + MAX_CHN + 2) && + (mousex >= dpos.orderlistX)) { - int newpos = esview + (mousex-44-10) / 3; - int newcolumn = (mousex-44-10) % 3; + int newpos = esview + (mousex-(dpos.orderlistX+4)) / 3; + int newcolumn = (mousex-(dpos.orderlistX+4)) % 3; int newchn = mousey - 3; if (newcolumn < 0) newcolumn = 0; if (newcolumn > 1) newcolumn = 1; @@ -791,31 +798,43 @@ void mousecommands(void) if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (newpos < songlen[esnum][eschn])) esmarkend = newpos; } - if (((!prevmouseb) || (mouseheld > HOLDDELAY)) && (mousey == 2) && (mousex >= 63+10) && (mousex <= 64+10)) + if (((!prevmouseb) || (mouseheld > HOLDDELAY)) && + (mousey == dpos.orderlistY) && + (mousex >= dpos.orderlistX+23) && (mousex <= dpos.orderlistX+24)) { if (mouseb & MOUSEB_LEFT) nextsong(); if (mouseb & MOUSEB_RIGHT) prevsong(); } // Instrument editpos & instrument number selection - if ((mousey >= 8) && (mousey <= 12) && (mousex >= 56+10) && (mousex <= 57+10)) + if ((mousey >= dpos.instrumentsY+1) && + (mousey <= dpos.instrumentsY+5) && + (mousex >= (dpos.instrumentsX+16)) && + (mousex <= (dpos.instrumentsX+17))) { editmode = EDIT_INSTRUMENT; - eipos = mousey-8; - eicolumn = mousex-56-10; + eipos = mousey-(dpos.instrumentsY+1); + eicolumn = mousex-(dpos.instrumentsX+16); } - if ((mousey >= 8) && (mousey <= 11) && (mousex >= 76+10) && (mousex <= 77+10)) + if ((mousey >= dpos.instrumentsY+1) && + (mousey <= dpos.instrumentsY+4) && + (mousex >= dpos.instrumentsX+36) && + (mousex <= dpos.instrumentsX+37)) { editmode = EDIT_INSTRUMENT; - eipos = mousey-8+5; - eicolumn = mousex-76-10; + eipos = mousey-(dpos.instrumentsY+1)+5; + eicolumn = mousex-(dpos.instrumentsX+36); } - if ((mousey == 7) && (mousex >= 60+10)) + if ((mousey == dpos.instrumentsY) && + (mousex >= dpos.instrumentsX+20)) { editmode = EDIT_INSTRUMENT; eipos = 9; } - if (((!prevmouseb) || (mouseheld > HOLDDELAY)) && (mousey == 7) && (mousex >= 56+10) && (mousex <= 57+10)) + if (((!prevmouseb) || (mouseheld > HOLDDELAY)) && + (mousey == dpos.instrumentsY) && + (mousex >= dpos.instrumentsX+16) && + (mousex <= dpos.instrumentsX+17)) { if (mouseb & MOUSEB_LEFT) nextinstr(); if (mouseb & MOUSEB_RIGHT) previnstr(); @@ -825,9 +844,12 @@ void mousecommands(void) // Table editpos for (c = 0; c < MAX_TABLES; c++) { - if ((mousey >= 14) && (mousey <= 30) && (mousex >= 43+10+c*10) && (mousex <= 47+10+c*10)) + if ((mousey >= dpos.instrumentsY+7) && + (mousey <= dpos.instrumentsY+8+VISIBLETABLEROWS-1) && + (mousex >= dpos.instrumentsX+3+c*10) && + (mousex <= dpos.instrumentsX+7+10+c*10)) { - int newpos = mousey-15+etview[etnum]; + int newpos = mousey-(dpos.instrumentsY+7)+etview[etnum]; if (newpos < 0) newpos = 0; if (newpos >= MAX_TABLELEN) newpos = MAX_TABLELEN-1; @@ -844,8 +866,8 @@ void mousecommands(void) if (mouseb & MOUSEB_LEFT) { etnum = c; - etpos = mousey-15+etview[etnum]; - etcolumn = mousex-43-10-c*10; + etpos = mousey-(dpos.instrumentsY+8)+etview[etnum]; + etcolumn = mousex-(dpos.instrumentsX+3)-c*10; } if (etcolumn >= 2) etcolumn--; if (etpos < 0) etpos = 0; @@ -856,60 +878,72 @@ void mousecommands(void) } // Name editpos - if ((mousey >= 31) && (mousey <= 33) && (mousex >= 49+10)) + if ((mousey >= dpos.instrumentsY+8+VISIBLETABLEROWS+1) && + (mousey <= dpos.instrumentsY+8+VISIBLETABLEROWS+3) && + (mousex >= dpos.instrumentsX+9)) { editmode = EDIT_NAMES; - enpos = mousey - 31; + enpos = mousey - (dpos.instrumentsY+8+VISIBLETABLEROWS+1); } // Status panel - if ((!prevmouseb) && (mousex == 7) && (mousey == 23+3+9)) + if ((!prevmouseb) && + (mousex == dpos.octaveX+7) && + (mousey == dpos.octaveY)) { if (mouseb & (MOUSEB_LEFT)) if (epoctave < 7) epoctave++; if (mouseb & (MOUSEB_RIGHT)) if (epoctave > 0) epoctave--; } - if ((!prevmouseb) && (mousex <= 7) && (mousey == 24+3+9)) + if ((!prevmouseb) && (mousex <= dpos.octaveX+7) && (mousey == dpos.octaveY+1)) { recordmode ^= 1; } for (c = 0; c < MAX_CHN; c++) { - if ((!prevmouseb) && (mousey >= 23+3+9) && (mousex >= 80 + 7*c) && (mousex <= 85 + 7*c)) + if ((!prevmouseb) && + (mousey >= dpos.channelsY) && + (mousex >= dpos.channelsX + 7*c) && + (mousex <= dpos.channelsX+5 + 7*c)) mutechannel(c); } // Titlebar actions if (!menu) { - if ((mousey == 0) && (!prevmouseb) && (mouseb == MOUSEB_LEFT)) + if ((mousey == dpos.statusTopY) && (!prevmouseb) && (mouseb == MOUSEB_LEFT)) { - if ((mousex >= 40+10) && (mousex <= 41+10)) + if ((mousex >= dpos.statusTopFvX) && (mousex <= dpos.statusTopFvX+1)) { usefinevib ^= 1; } - if ((mousex >= 43+10) && (mousex <= 44+10)) + if ((mousex >= dpos.statusTopFvX+3) && (mousex <= dpos.statusTopFvX+4)) { optimizepulse ^= 1; } - if ((mousex >= 46+10) && (mousex <= 47+10)) + if ((mousex >= dpos.statusTopFvX+6) && (mousex <= dpos.statusTopFvX+7)) { optimizerealtime ^= 1; } - if ((mousex >= 49+10) && (mousex <= 52+10)) + if ((mousex >= dpos.statusTopFvX+9) && (mousex <= dpos.statusTopFvX+12)) { ntsc ^= 1; sound_init(mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate, exsid, filterbias, combwaves); } - if ((mousex >= 54+10) && (mousex <= 57+10)) + if ((mousex >= dpos.statusTopFvX+14) && (mousex <= dpos.statusTopFvX+17)) { sidmodel ^= 1; sound_init(mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate, exsid, filterbias, combwaves); } - if ((mousex >= 62+10) && (mousex <= 65+10)) editadsr(); - if ((mousex >= 67+10) && (mousex <= 68+10)) prevmultiplier(); - if ((mousex >= 69+10) && (mousex <= 70+10)) nextmultiplier(); + if ((mousex >= dpos.statusTopFvX+22) && + (mousex <= dpos.statusTopFvX+25)) editadsr(); + if ((mousex >= dpos.statusTopFvX+27) && + (mousex <= dpos.statusTopFvX+28)) prevmultiplier(); + if ((mousex >= dpos.statusTopFvX+29) && + (mousex <= dpos.statusTopFvX+30)) nextmultiplier(); + if ((mousex >= dpos.statusTopEndX-8) && + (mousex <= dpos.statusTopEndX-1)) onlinehelp(0,0); } } else @@ -1224,9 +1258,9 @@ void quit(void) { if ((!shiftpressed) || (mouseb)) { - printtextcp(49, 36, 15, "Really Quit (y/n)?"); + printtextcp(dpos.statusBottomX+29, dpos.statusBottomY, 15, "Really Quit (y/n)?"); waitkey(); - printblank(20, 36, 58); + printblank(20, 39, 58); if ((key == 'y') || (key == 'Y')) exitprogram = 1; } key = 0; @@ -1241,9 +1275,9 @@ void clear(void) int ct = 0; int cn = 0; - printtextcp(49, 36, 15, "Optimize everything (y/n)?"); + printtextcp(dpos.statusBottomX+29, dpos.statusBottomY, 15, "Optimize everything (y/n)?"); waitkey(); - printblank(20, 36, 58); + printblank(dpos.statusBottomX, dpos.statusBottomY, 58); if ((key == 'y') || (key == 'Y')) { optimizeeverything(1, 1); @@ -1252,29 +1286,29 @@ void clear(void) return; } - printtextcp(49, 36, 15, "Clear orderlists (y/n)?"); + printtextcp(dpos.statusBottomX+29, dpos.statusBottomY, 15, "Clear orderlists (y/n)?"); waitkey(); - printblank(20, 36, 58); + printblank(dpos.statusBottomX, dpos.statusBottomY, 58); if ((key == 'y') || (key == 'Y')) cs = 1; - printtextcp(49, 36, 15, "Clear patterns (y/n)?"); + printtextcp(dpos.statusBottomX+29, dpos.statusBottomY, 15, "Clear patterns (y/n)?"); waitkey(); - printblank(20, 36, 58); + printblank(dpos.statusBottomX, dpos.statusBottomY, 58); if ((key == 'y') || (key == 'Y')) cp = 1; - printtextcp(49, 36, 15, "Clear instruments (y/n)?"); + printtextcp(dpos.statusBottomX+29, dpos.statusBottomY, 15, "Clear instruments (y/n)?"); waitkey(); - printblank(20, 36, 58); + printblank(dpos.statusBottomX, dpos.statusBottomY, 58); if ((key == 'y') || (key == 'Y')) ci = 1; - printtextcp(49, 36, 15, "Clear tables (y/n)?"); + printtextcp(dpos.statusBottomX+29, dpos.statusBottomY, 15, "Clear tables (y/n)?"); waitkey(); - printblank(20, 36, 58); + printblank(dpos.statusBottomX, dpos.statusBottomY, 58); if ((key == 'y') || (key == 'Y')) ct = 1; - printtextcp(49, 36, 15, "Clear songname (y/n)?"); + printtextcp(dpos.statusBottomX+29, dpos.statusBottomY, 15, "Clear songname (y/n)?"); waitkey(); - printblank(20, 36, 58); + printblank(dpos.statusBottomX, dpos.statusBottomY, 58); if ((key == 'y') || (key == 'Y')) cn = 1; if (cp == 1) @@ -1282,11 +1316,18 @@ void clear(void) int selectdone = 0; int olddpl = defaultpatternlength; - printtext(40, 36, 15,"Pattern length:"); + printtext(dpos.statusBottomX+20, dpos.statusBottomY, 15,"Pattern length:"); while (!selectdone) { - sprintf(textbuffer, "%02d ", defaultpatternlength); - printtext(55, 36, 15, textbuffer); + if (patterndispmode) + { + sprintf(textbuffer, "%02X ", defaultpatternlength); + } + else + { + sprintf(textbuffer, "%02d ", defaultpatternlength); + } + printtext(dpos.statusBottomX+35, dpos.statusBottomY, 15, textbuffer); waitkey(); switch(rawkey) { @@ -1316,7 +1357,7 @@ void clear(void) break; } } - printblank(20, 36, 58); + printblank(dpos.statusBottomX, dpos.statusBottomY, 58); } if (cs | cp | ci | ct | cn) diff --git a/src/goattrk2.h b/src/goattrk2.h index 8d0d6c0..07da6df 100644 --- a/src/goattrk2.h +++ b/src/goattrk2.h @@ -35,10 +35,11 @@ #define KEY_DMC 1 #define KEY_JANKO 2 -#define VISIBLEPATTROWS 31 -#define VISIBLEORDERLIST 15 +#define VISIBLEPATTROWS 34 +#define VISIBLEORDERLIST 14 +#define VISIBLEORDERLISTMONO 23 #define VISIBLETABLEROWS 15 -#define VISIBLEFILES 24 +#define VISIBLEFILES 28 #define PGUPDNREPEAT 8 diff --git a/src/gpattern.c b/src/gpattern.c index e10f91a..8d067fa 100644 --- a/src/gpattern.c +++ b/src/gpattern.c @@ -120,7 +120,7 @@ void patterncommands(void) } } break; - + case KEY_JANKO: for (i = 0; i < sizeof(jankokeytbl1); i++) { From 6749469c7e0829f0a196cdfe6161cf5bf9402064 Mon Sep 17 00:00:00 2001 From: Leandro Nini Date: Sun, 5 Jul 2026 09:26:31 +0200 Subject: [PATCH 02/15] Apply changes from fork https://github.com/jansalleine/gt2fork/commit/a86063450fc558cdfb44e1ada3ca0ddcff378dd1 https://github.com/jansalleine/gt2fork/commit/6334a7c8f41f434dc90c6862dcbfc5a4467434fd https://github.com/jansalleine/gt2fork/commit/1a4adc05e4694b5c2a8d53d630f42660717336c6 --- src/bcursor.bin | Bin 615 -> 0 bytes src/gconsole.c | 196 +++++------------------------------------------- src/gconsole.h | 1 - src/gdisplay.c | 21 ++++-- src/goattrk2.c | 25 ++---- src/goattrk2.h | 4 +- 6 files changed, 45 insertions(+), 202 deletions(-) delete mode 100644 src/bcursor.bin diff --git a/src/bcursor.bin b/src/bcursor.bin deleted file mode 100644 index 2090e55ae2c33d9ebd6258c323a8e3ffc17516a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 615 zcmaiy-3mZJ5JpEyk|aqU!E?HBC3)ku`wct$Yn7du^Bqc~BBF&heezYCqWEldr}X{R z*32N%b<9BBzW+E9e;Oo18qTAe!-&b`JFrr04n3G@y2LK*9A8sDp2#Qhm;4ZZzdo&F e2{vGMwaYG244XW}3FlLyVta{OY;XRB-a-%h5Nvk< diff --git a/src/gconsole.c b/src/gconsole.c index f28c0d0..40319eb 100644 --- a/src/gconsole.c +++ b/src/gconsole.c @@ -31,7 +31,6 @@ int fontwidth = 8; int fontheight = 14; int mousesizex = 11; int mousesizey = 20; -unsigned bigwindow = 1; POSITIONS dpos = { @@ -76,14 +75,6 @@ int initscreen(void) printf("xsize: %d, ysize: %d", xsize, ysize); - if (bigwindow > 1) - { - fontwidth *= bigwindow; - fontheight *= bigwindow; - mousesizex *= 2; - mousesizey *= 2; - } - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) return 0; win_openwindow(xsize, ysize, "LoadTracker", NULL); @@ -114,8 +105,7 @@ int initscreen(void) loadexternalpalette(); gfx_setpalette(); - if (bigwindow - 1) gfx_loadsprites(0, "bcursor.bin"); - else gfx_loadsprites(0, "cursor.bin"); + gfx_loadsprites(0, "cursor.bin"); gfxinitted = 1; clearscreen(); @@ -402,172 +392,24 @@ void fliptoscreen(void) for (c = 0; c < 14; c++) { e = *chptr++; - - switch (bigwindow) - { - case 1: - if (e & 128) *dptr++ = fgcolor; - else *dptr++ = bgcolor; - if (e & 64) *dptr++ = fgcolor; - else *dptr++ = bgcolor; - if (e & 32) *dptr++ = fgcolor; - else *dptr++ = bgcolor; - if (e & 16) *dptr++ = fgcolor; - else *dptr++ = bgcolor; - if (e & 8) *dptr++ = fgcolor; - else *dptr++ = bgcolor; - if (e & 4) *dptr++ = fgcolor; - else *dptr++ = bgcolor; - if (e & 2) *dptr++ = fgcolor; - else *dptr++ = bgcolor; - if (e & 1) *dptr++ = fgcolor; - else *dptr++ = bgcolor; - dptr += gfx_screen->pitch - fontwidth; - break; - case 2: - if (e & 128) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 64) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 32) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 16) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 8) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 4) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 2) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 1) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - dptr += gfx_screen->pitch - fontwidth; - if (e & 128) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 64) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 32) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 16) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 8) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 4) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 2) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 1) {*dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor;} - dptr += gfx_screen->pitch - fontwidth; - break; - case 3: - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - dptr += gfx_screen->pitch - fontwidth; - if (e & 128) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 64) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 32) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 16) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 8) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 4) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 2) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 1) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - dptr += gfx_screen->pitch - fontwidth; - if (e & 128) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 64) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 32) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 16) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 8) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 4) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 2) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 1) {*dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - dptr += gfx_screen->pitch - fontwidth; - break; - case 4: - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; - dptr += gfx_screen->pitch - fontwidth; - if (e & 128) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 64) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 32) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 16) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 8) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 4) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 2) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 1) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - dptr += gfx_screen->pitch - fontwidth; - if (e & 128) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 64) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 32) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 16) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 8) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 4) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 2) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 1) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - dptr += gfx_screen->pitch - fontwidth; - if (e & 128) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 64) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 32) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 16) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 8) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 4) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 2) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - if (e & 1) {*dptr++ = bgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor; *dptr++ = fgcolor;} - else {*dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor; *dptr++ = bgcolor;} - dptr += gfx_screen->pitch - fontwidth; - break; - } + + if (e & 128) *dptr++ = fgcolor; + else *dptr++ = bgcolor; + if (e & 64) *dptr++ = fgcolor; + else *dptr++ = bgcolor; + if (e & 32) *dptr++ = fgcolor; + else *dptr++ = bgcolor; + if (e & 16) *dptr++ = fgcolor; + else *dptr++ = bgcolor; + if (e & 8) *dptr++ = fgcolor; + else *dptr++ = bgcolor; + if (e & 4) *dptr++ = fgcolor; + else *dptr++ = bgcolor; + if (e & 2) *dptr++ = fgcolor; + else *dptr++ = bgcolor; + if (e & 1) *dptr++ = fgcolor; + else *dptr++ = bgcolor; + dptr += gfx_screen->pitch - fontwidth; } } } diff --git a/src/gconsole.h b/src/gconsole.h index 804be6d..d6693e0 100644 --- a/src/gconsole.h +++ b/src/gconsole.h @@ -47,7 +47,6 @@ extern int key, rawkey, shiftpressed, cursorflashdelay; extern int mouseb, prevmouseb; extern int mouseheld; extern int mousex, mousey; -extern unsigned bigwindow; extern POSITIONS dpos; #endif diff --git a/src/gdisplay.c b/src/gdisplay.c index 0ba2ed9..e0dc7f9 100644 --- a/src/gdisplay.c +++ b/src/gdisplay.c @@ -62,6 +62,7 @@ void printstatus(void) { int c, d, color, color2; int cc = cursorcolortable[cursorflash]; + int visibleOrderlist = VISIBLEORDERLIST; menu = 0; if ((mouseb > MOUSEB_LEFT) && (mousey <= 1) && (!eamode)) menu = 1; @@ -141,9 +142,9 @@ void printstatus(void) { esview = newpos; } - if (newpos - esview >= VISIBLEORDERLISTMONO) + if (newpos - esview >= visibleOrderlist) { - esview = newpos - VISIBLEORDERLISTMONO + 1; + esview = newpos - visibleOrderlist + 1; } } } @@ -256,13 +257,22 @@ void printstatus(void) } } - sprintf(textbuffer, "CHN ORDERLIST (SUBTUNE %02X, POS %02X)", esnum, eseditpos); + sprintf(textbuffer, "CHN ORDERLIST (SUBTUNE ", esnum, eseditpos); printtext(dpos.orderlistX, dpos.orderlistY, colors.CTITLE, textbuffer); + sprintf(textbuffer, "%02X", esnum); + printtext(dpos.orderlistX+23, dpos.orderlistY, colors.CEDIT, textbuffer); + sprintf(textbuffer, ", POS "); + printtext(dpos.orderlistX+25, dpos.orderlistY, colors.CTITLE, textbuffer); + sprintf(textbuffer, "%02X", eseditpos); + printtext(dpos.orderlistX+31, dpos.orderlistY, colors.CEDIT, textbuffer); + sprintf(textbuffer, ")"); + printtext(dpos.orderlistX+33, dpos.orderlistY, colors.CTITLE, textbuffer); + for (c = 0; c < MAX_CHN; c++) { sprintf(textbuffer, " %d ", c+1); printtext(dpos.orderlistX, dpos.orderlistY+1+c, colors.CTITLE, textbuffer); - for (d = 0; d < VISIBLEORDERLISTMONO; d++) + for (d = 0; d < visibleOrderlist; d++) { int p = esview+d; color = colors.CNORMAL; @@ -317,6 +327,7 @@ void printstatus(void) if (color == colors.CNORMAL) color = colors.CCOMMAND; } } + if (chn[c].mute) color = colors.CMUTE; printtext(dpos.orderlistX+4+d*3, dpos.orderlistY+1+c, color, textbuffer); if (c == esmarkchn) { @@ -535,7 +546,7 @@ void printstatus(void) sprintf(textbuffer, "%03X/%02X", chnpos,chnrow); - printtext(dpos.channelsX+7*c, dpos.channelsY+1, colors.CEDIT, textbuffer); + printtext(dpos.channelsX+7*c, dpos.channelsY+1, chn[c].mute ? colors.CMUTE : colors.CEDIT, textbuffer); } if (etlock) printtext(dpos.channelsX-2, dpos.channelsY+1, colors.CTITLE, " "); diff --git a/src/goattrk2.c b/src/goattrk2.c index 00892a2..81f1862 100644 --- a/src/goattrk2.c +++ b/src/goattrk2.c @@ -72,7 +72,7 @@ float filterbias = 0.5f; float equaldivisionsperoctave = 12.0f; int tuningcount = 0; double tuning[96]; -extern unsigned bigwindow; +unsigned numsids = 1; char configbuf[MAX_PATHNAME]; char loadedsongfilename[MAX_FILENAME]; @@ -107,7 +107,7 @@ char* usage[] = { "-Dxx Pattern row display (0 = decimal, 1 = hex, 2 = decimal w/dots, 3 = hex w/dots) DEFAULT=2", "-Exx Set emulated SID model (0 = 6581 1 = 8580) DEFAULT=8580", "-Fxx Set custom SID clock cycles per second (0 = use PAL/NTSC default)", - "-Gxx Set pitch of A-4 in Hz (0 = use default frequencytable, close to 440Hz)", + "-Gxx Set pitch of A-4 in Hz (0 = use default frequency table, close to 440Hz)", "-Hxx Use HardSID (0 = off, 1 = HardSID ID0 2 = HardSID ID1 etc.)", "-Ixx Set reSIDfp resampling mode (0 = fast, 1 = interpolation, 2 = resampling, 3 = fastmem resampling) DEFAULT=2", "-Jxx Set special note names (2 chars for every note in an octave/cycle, e.g. C-DbD-EbE-F-GbG-AbA-BbB-)", @@ -124,9 +124,8 @@ char* usage[] = { "-Xxx Set window type (0 = window, 1 = fullscreen) DEFAULT=window", "-Yxx Path to a Scala tuning file .scl", "-Zxx Set random reSIDfp write delay in cycles (0 = off) DEFAULT=off", - "-bxx Set filter curve (0.0 (dark) to 1.0 (light))", + "-bxx Set filter curve (0.0 (dark) to 1.0 (bright))", "-cxx Set combined waveforms strength (0 weak, 1 average, 2 strong) DEFAULT=average" - "-wxx Set window scale factor (1 = no scaling, 2 to 4 = 2 to 4 times bigger window) DEFAULT=1", "-xxx Use exdSID (0 = off, 1 = on)", "-N Use NTSC timing", "-P Use PAL timing (DEFAULT)", @@ -201,7 +200,6 @@ int main(int argc, char **argv) getparam(configfile, &hardsidbufinteractive); getparam(configfile, &hardsidbufplayback); getparam(configfile, (unsigned*)&win_fullscreen); - getparam(configfile, &bigwindow); getparam(configfile, &combwaves); getfloatparam(configfile, &basepitch); getfloatparam(configfile, &filterbias); @@ -349,27 +347,23 @@ int main(int argc, char **argv) case 'b': sscanf(&argv[c][2], "%f", &filterbias); break; - + case 'c': sscanf(&argv[c][2], "%f", &combwaves); break; - + case 'Q': sscanf(&argv[c][2], "%f", &equaldivisionsperoctave); break; - + case 'J': sscanf(&argv[c][2], "%s", specialnotenames); break; - + case 'Y': sscanf(&argv[c][2], "%s", scalatuningfilepath); break; - - case 'w': - sscanf(&argv[c][2], "%u", &bigwindow); - break; - + case 'x': sscanf(&argv[c][2], "%u", &exsid); break; @@ -413,8 +407,6 @@ int main(int argc, char **argv) if (optimizerealtime > 1) optimizerealtime = 1; if (residdelay > 63) residdelay = 63; if (customclockrate < 100) customclockrate = 0; - if (bigwindow < 1) bigwindow = 1; - if (bigwindow > 4) bigwindow = 4; if (combwaves < 0) combwaves = 0; else if (combwaves > 2) combwaves = 2; if (filterbias < 0.0) filterbias = 0.0; @@ -551,7 +543,6 @@ int main(int argc, char **argv) hardsidbufinteractive, hardsidbufplayback, win_fullscreen, - bigwindow, basepitch, filterbias, combwaves, diff --git a/src/goattrk2.h b/src/goattrk2.h index 07da6df..a0cfe03 100644 --- a/src/goattrk2.h +++ b/src/goattrk2.h @@ -36,8 +36,7 @@ #define KEY_JANKO 2 #define VISIBLEPATTROWS 34 -#define VISIBLEORDERLIST 14 -#define VISIBLEORDERLISTMONO 23 +#define VISIBLEORDERLIST 23 #define VISIBLETABLEROWS 15 #define VISIBLEFILES 28 @@ -79,6 +78,7 @@ extern unsigned hardsid; extern unsigned catweasel; extern unsigned exsid; extern unsigned interpolate; +extern unsigned numsids; extern unsigned hardsidbufinteractive; extern unsigned hardsidbufplayback; extern float basepitch; From 6b943b3b3de364193ce191e1c4ec08f34136b9e8 Mon Sep 17 00:00:00 2001 From: Leandro Nini Date: Sun, 5 Jul 2026 10:38:26 +0200 Subject: [PATCH 03/15] Apply changes from fork https://github.com/jansalleine/gt2fork/commit/74b0e27d391c1e35b0bfdbb74e83c5c8bfa08410 https://github.com/jansalleine/gt2fork/commit/1fb1d68c5c80964d42b1db02aa0f8c9f58c41332 --- src/cwsid.h | 29 ---- src/goattrk2.c | 53 ++----- src/goattrk2.h | 4 - src/gsound.c | 364 ++----------------------------------------------- src/gsound.h | 15 +- src/gt2reloc.c | 4 - 6 files changed, 21 insertions(+), 448 deletions(-) delete mode 100644 src/cwsid.h diff --git a/src/cwsid.h b/src/cwsid.h deleted file mode 100644 index 6316234..0000000 --- a/src/cwsid.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef DEVSID__H -#define DEVSID__H - -/* The ioctl numbers are modelled after the hardsid linux device - driver, so a software may autodetect which device is present behind - a /dev/sid. - http://hardsid.sourceforge.net/ - */ - -#define CWSID_IOCTL_TYPE ('S') - -#define CWSID_IOCTL_RESET _IO (CWSID_IOCTL_TYPE, 0) -#define CWSID_IOCTL_SIDTYPE _IOR(CWSID_IOCTL_TYPE, 3, int) -#define CWSID_IOCTL_CARDTYPE _IOR(CWSID_IOCTL_TYPE, 4, int) - -#define CWSID_IOCTL_WAITIRQ _IO(CWSID_IOCTL_TYPE, 0x10) -#define CWSID_IOCTL_PAL _IO(CWSID_IOCTL_TYPE, 0x11) -#define CWSID_IOCTL_NTSC _IO(CWSID_IOCTL_TYPE, 0x12) - -#define CWSID_IOCTL_SETHZ _IOW(CWSID_IOCTL_TYPE, 0x20,int) -#define CWSID_IOCTL_DOUBLEBUFFER _IOW(CWSID_IOCTL_TYPE, 0x21,int) -#define CWSID_IOCTL_DELAY _IOW(CWSID_IOCTL_TYPE, 0x22,int) -#define CWSID_IOCTL_REALREAD _IOW(CWSID_IOCTL_TYPE, 0x23,int) - -/* a magic number used by the CWSID_IOCTL_SIDTYPE and - CWSID_IOCTL_CARDTYPE ioctls to identify a CatWeasel SID */ -#define CWSID_MAGIC 0x100 - -#endif diff --git a/src/goattrk2.c b/src/goattrk2.c index 81f1862..119774a 100644 --- a/src/goattrk2.c +++ b/src/goattrk2.c @@ -59,13 +59,9 @@ unsigned customclockrate = 0; unsigned usefinevib = 0; unsigned mr = DEFAULTMIXRATE; unsigned writer = 0; -unsigned hardsid = 0; -unsigned catweasel = 0; unsigned exsid = 0; unsigned interpolate = 1; unsigned residdelay = 0; -unsigned hardsidbufinteractive = 20; -unsigned hardsidbufplayback = 400; unsigned combwaves = 1; float basepitch = 0.0f; float filterbias = 0.5f; @@ -103,12 +99,10 @@ char* usage[] = { "Usage: loadtrk [songname] [options]", "Options:", "-Axx Set ADSR parameter for hardrestart in hex. DEFAULT=0F00", - "-Cxx Use CatWeasel MK3 PCI SID (0 = off, 1 = on)", "-Dxx Pattern row display (0 = decimal, 1 = hex, 2 = decimal w/dots, 3 = hex w/dots) DEFAULT=2", "-Exx Set emulated SID model (0 = 6581 1 = 8580) DEFAULT=8580", "-Fxx Set custom SID clock cycles per second (0 = use PAL/NTSC default)", "-Gxx Set pitch of A-4 in Hz (0 = use default frequency table, close to 440Hz)", - "-Hxx Use HardSID (0 = off, 1 = HardSID ID0 2 = HardSID ID1 etc.)", "-Ixx Set reSIDfp resampling mode (0 = fast, 1 = interpolation, 2 = resampling, 3 = fastmem resampling) DEFAULT=2", "-Jxx Set special note names (2 chars for every note in an octave/cycle, e.g. C-DbD-EbE-F-GbG-AbA-BbB-)", "-Kxx Note-entry mode (0 = Protracker, 1 = DMC, 2 = Janko) DEFAULT=Protracker", @@ -118,8 +112,6 @@ char* usage[] = { "-Qxx Set equal divisions per octave (12 = default, 8.2019143 = Bohlen-Pierce)", "-Rxx Set realtime-effect optimization/skipping (0 = off, 1 = on) DEFAULT=on", "-Sxx Set speed multiplier (0 for 25Hz, 1 for 1x, 2 for 2x etc.)", - "-Txx Set HardSID interactive mode sound buffer length in milliseconds DEFAULT=20, max.buffering=0", - "-Uxx Set HardSID playback mode sound buffer length in milliseconds DEFAULT=400, max.buffering=0", "-Vxx Set finevibrato conversion (0 = off, 1 = on) DEFAULT=on", "-Xxx Set window type (0 = window, 1 = fullscreen) DEFAULT=window", "-Yxx Path to a Scala tuning file .scl", @@ -173,11 +165,9 @@ int main(int argc, char **argv) specialnotenames[0] = 0; scalatuningfilepath[0] = 0; configfile = fopen(filename, "rt"); - unsigned dummy; // for compatibility if (configfile) { getparam(configfile, &mr); - getparam(configfile, &hardsid); getparam(configfile, &sidmodel); getparam(configfile, &ntsc); getparam(configfile, (unsigned *)&fileformat); @@ -187,7 +177,6 @@ int main(int argc, char **argv) getparam(configfile, &keypreset); getparam(configfile, (unsigned *)&stepsize); getparam(configfile, &multiplier); - getparam(configfile, &catweasel); getparam(configfile, &adparam); getparam(configfile, &interpolate); getparam(configfile, &patterndispmode); @@ -197,8 +186,6 @@ int main(int argc, char **argv) getparam(configfile, &optimizerealtime); getparam(configfile, &residdelay); getparam(configfile, &customclockrate); - getparam(configfile, &hardsidbufinteractive); - getparam(configfile, &hardsidbufplayback); getparam(configfile, (unsigned*)&win_fullscreen); getparam(configfile, &combwaves); getfloatparam(configfile, &basepitch); @@ -312,22 +299,10 @@ int main(int argc, char **argv) sscanf(&argv[c][2], "%u", &optimizerealtime); break; - case 'H': - sscanf(&argv[c][2], "%u", &hardsid); - break; - case 'V': sscanf(&argv[c][2], "%u", &finevibrato); break; - case 'T': - sscanf(&argv[c][2], "%u", &hardsidbufinteractive); - break; - - case 'U': - sscanf(&argv[c][2], "%u", &hardsidbufplayback); - break; - case 'W': writer = 1; break; @@ -336,10 +311,6 @@ int main(int argc, char **argv) sscanf(&argv[c][2], "%d", &win_fullscreen); break; - case 'C': - sscanf(&argv[c][2], "%u", &catweasel); - break; - case 'G': sscanf(&argv[c][2], "%f", &basepitch); break; @@ -439,7 +410,7 @@ int main(int argc, char **argv) clearsong(1,1,1,1,1); // Init sound - if (!sound_init(mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate, exsid, filterbias, combwaves)) + if (!sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves)) { printtextc(MAX_ROWS/2-1,15,"Sound init failed. Press any key to run without sound (notice that song timer won't start)"); waitkeynoupdate(); @@ -483,12 +454,11 @@ int main(int argc, char **argv) if (configfile) { fprintf(configfile, ";------------------------------------------------------------------------------\n" - ";LT config file. Rows starting with ; are comments. Hexadecimal parameters are \n" - ";to be preceded with $ and decimal parameters with nothing. \n" + ";LoadTracker config file. Rows starting with ; are comments. \n" + ";Hex parameters are to be preceded with $ and decimal parameters with nothing. \n" ";------------------------------------------------------------------------------\n" "\n" ";reSIDfp mixing rate (in Hz)\n%d\n\n" - ";Hardsid device number (0 = off)\n%d\n\n" ";reSIDfp model (0 = 6581, 1 = 8580)\n%d\n\n" ";Timing mode (0 = PAL, 1 = NTSC)\n%d\n\n" ";Packer/relocator fileformat (0 = SID, 1 = PRG, 2 = BIN)\n%d\n\n" @@ -498,7 +468,6 @@ int main(int argc, char **argv) ";Key entry mode (0 = Protracker, 1 = DMC, 2 = Janko)\n%d\n\n" ";Pattern highlight step size\n%d\n\n" ";Speed multiplier (0 = 25Hz, 1 = 1X, 2 = 2X etc.)\n%d\n\n" - ";Use CatWeasel SID (0 = off, 1 = on)\n%d\n\n" ";Hardrestart ADSR parameter\n$%04x\n\n" ";reSIDfp resampling mode (0 = interpolation, 1 = resampling)\n%d\n\n" ";Pattern display mode (0 = decimal, 1 = hex, 2 = decimal w/dots, 3 = hex w/dots)\n%d\n\n" @@ -508,8 +477,6 @@ int main(int argc, char **argv) ";Realtime effect skipping (0 = off, 1 = on)\n%d\n\n" ";Random reSIDfp write delay in cycles (0 = off)\n%d\n\n" ";Custom SID clock cycles per second (0 = use PAL/NTSC default)\n%d\n\n" - ";HardSID interactive mode buffer size (in milliseconds, 0 = maximum/no flush)\n%d\n\n" - ";HardSID playback mode buffer size (in milliseconds, 0 = maximum/no flush)\n%d\n\n" ";Window type (0 = window, 1 = fullscreen)\n%d\n\n" ";window scale factor (1 = no scaling, 2 to 4 = 2 to 4 times bigger window)\n%d\n\n" ";Base pitch of A-4 in Hz (0 = use default frequencytable)\n%f\n\n" @@ -520,7 +487,6 @@ int main(int argc, char **argv) ";Path to a Scala tuning file .scl\n%s\n\n" ";Use exSID (0 = off, 1 = on)\n%d\n\n", mr, - hardsid, sidmodel, ntsc, fileformat, @@ -530,7 +496,6 @@ int main(int argc, char **argv) keypreset, stepsize, multiplier, - catweasel, adparam, interpolate, patterndispmode, @@ -540,8 +505,6 @@ int main(int argc, char **argv) optimizerealtime, residdelay, customclockrate, - hardsidbufinteractive, - hardsidbufplayback, win_fullscreen, basepitch, filterbias, @@ -920,12 +883,12 @@ void mousecommands(void) if ((mousex >= dpos.statusTopFvX+9) && (mousex <= dpos.statusTopFvX+12)) { ntsc ^= 1; - sound_init(mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate, exsid, filterbias, combwaves); + sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves); } if ((mousex >= dpos.statusTopFvX+14) && (mousex <= dpos.statusTopFvX+17)) { sidmodel ^= 1; - sound_init(mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate, exsid, filterbias, combwaves); + sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves); } if ((mousex >= dpos.statusTopFvX+22) && (mousex <= dpos.statusTopFvX+25)) editadsr(); @@ -1150,7 +1113,7 @@ void generalcommands(void) else { sidmodel ^= 1; - sound_init( mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate, exsid, filterbias, combwaves); + sound_init( mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves); } break; @@ -1525,7 +1488,7 @@ void prevmultiplier(void) if (multiplier > 0) { multiplier--; - sound_init(mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate, exsid, filterbias, combwaves); + sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves); } } @@ -1534,7 +1497,7 @@ void nextmultiplier(void) if (multiplier < 16) { multiplier++; - sound_init(mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate, exsid, filterbias, combwaves); + sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves); } } diff --git a/src/goattrk2.h b/src/goattrk2.h index a0cfe03..d1e3531 100644 --- a/src/goattrk2.h +++ b/src/goattrk2.h @@ -74,13 +74,9 @@ extern unsigned usefinevib; extern unsigned b; extern unsigned mr; extern unsigned writer; -extern unsigned hardsid; -extern unsigned catweasel; extern unsigned exsid; extern unsigned interpolate; extern unsigned numsids; -extern unsigned hardsidbufinteractive; -extern unsigned hardsidbufplayback; extern float basepitch; extern char configbuf[MAX_PATHNAME]; extern char loadedsongfilename[MAX_FILENAME]; diff --git a/src/gsound.c b/src/gsound.c index 6f610ee..9f8c497 100644 --- a/src/gsound.c +++ b/src/gsound.c @@ -16,8 +16,6 @@ // General / reSID output int playspeed; -int usehardsid = 0; -int usecatweasel = 0; int useexsid = 0; int initted = 0; int firsttimeinit = 1; @@ -30,65 +28,19 @@ void sound_playrout(void); void sound_mixer(Sint32 *dest, unsigned samples); Uint32 sound_timer(void *userdata, SDL_TimerID timerID, Uint32 interval); -#ifdef __WIN32__ - -// Win32 HardSID output -typedef void (CALLBACK* lpWriteToHardSID)(Uint8 DeviceID, Uint8 SID_reg, Uint8 Data); -typedef Uint8 (CALLBACK* lpReadFromHardSID)(Uint8 DeviceID, Uint8 SID_reg); -typedef void (CALLBACK* lpInitHardSID_Mapper)(void); -typedef void (CALLBACK* lpMuteHardSID_Line)(int Mute); -typedef void (CALLBACK* lpHardSID_Delay)(Uint8 DeviceID, Uint16 Cycles); -typedef void (CALLBACK* lpHardSID_Write)(Uint8 DeviceID, Uint16 Cycles, Uint8 SID_reg, Uint8 Data); -typedef void (CALLBACK* lpHardSID_Flush)(Uint8 DeviceID); -typedef void (CALLBACK* lpHardSID_SoftFlush)(Uint8 DeviceID); -typedef boolean (CALLBACK* lpHardSID_Lock)(Uint8 DeviceID); -lpWriteToHardSID WriteToHardSID = NULL; -lpReadFromHardSID ReadFromHardSID = NULL; -lpInitHardSID_Mapper InitHardSID_Mapper = NULL; -lpMuteHardSID_Line MuteHardSID_Line = NULL; -lpHardSID_Delay HardSID_Delay = NULL; -lpHardSID_Write HardSID_Write = NULL; -lpHardSID_Flush HardSID_Flush = NULL; -lpHardSID_SoftFlush HardSID_SoftFlush = NULL; -lpHardSID_Lock HardSID_Lock = NULL; -HINSTANCE hardsiddll = 0; -int dll_initialized = FALSE; -// Cycle-exact HardSID support -int cycleexacthardsid = FALSE; -SDL_Thread* playerthread = NULL; -SDL_Mutex* flushmutex = NULL; -volatile int runplayerthread = FALSE; -volatile int flushplayerthread = FALSE; -volatile int suspendplayroutine = FALSE; -int sound_thread(void *userdata); - -void InitHardDLL(void); - -// Win32 CatWeasel MK3 PCI output -#define SID_SID_PEEK_POKE CTL_CODE(FILE_DEVICE_SOUND,0x0800UL + 1,METHOD_BUFFERED,FILE_ANY_ACCESS) -HANDLE catweaselhandle; - -#else - -// Unix HardSID & CatWeasel output -int hardsidfd = -1; -int catweaselfd = -1; - -#endif - #ifdef USE_EXSID void* exsidfd = NULL; unsigned exsidDelay = 0; #endif -int sound_init(unsigned mr, unsigned writer, unsigned hardsid, unsigned m, unsigned ntsc, unsigned multiplier, unsigned catweasel, unsigned interpolate, unsigned customclockrate, unsigned exsid, float filterbias, unsigned combwaves) +int sound_init(unsigned mr, unsigned writer, unsigned m, unsigned ntsc, + unsigned multiplier, unsigned interpolate, unsigned customclockrate, + unsigned exsid, float filterbias, unsigned combwaves) { - int c; - - #ifdef __WIN32__ +#ifdef __WIN32__ if (!flushmutex) flushmutex = SDL_CreateMutex(); - #endif +#endif sound_uninit(); @@ -119,93 +71,6 @@ int sound_init(unsigned mr, unsigned writer, unsigned hardsid, unsigned m, unsig } } - if (hardsid) - { - #ifdef __WIN32__ - InitHardDLL(); - if (dll_initialized) - { - usehardsid = hardsid; - if (cycleexacthardsid) { - HardSID_Lock(usehardsid-1); - HardSID_Flush(usehardsid-1); - HardSID_Write(usehardsid-1, SIDWRITEDELAY, 0, 0x00); - Sleep(300); - } - for (c = 0; c < NUMSIDREGS; c++) - { - sidreg[c] = 0; - if (cycleexacthardsid) { - HardSID_Write(usehardsid-1, SIDWRITEDELAY, c, 0x00); - } - else { - WriteToHardSID(usehardsid-1, c, 0x00); - } - } - if (cycleexacthardsid) { - HardSID_SoftFlush(usehardsid-1); - } - else { - MuteHardSID_Line(FALSE); - } - } - else return 0; - if (!cycleexacthardsid) - { - timer = SDL_AddTimer(1000 / framerate, sound_timer, NULL); - } - else - { - runplayerthread = TRUE; - playerthread = SDL_CreateThread(sound_thread, "Sound thread", NULL); - if (!playerthread) return 0; - } - #else - char filename[80]; - sprintf(filename, "/dev/sid%d", hardsid-1); - hardsidfd = open(filename, O_WRONLY, S_IRUSR|S_IWUSR); - if (hardsidfd >= 0) - { - usehardsid = hardsid; - for (c = 0; c < NUMSIDREGS; c++) - { - Uint32 dataword = c << 8; - write(hardsidfd, &dataword, 4); - } - } - else return 0; - timer = SDL_AddTimer(1000 / framerate, sound_timer, NULL); - #endif - - goto SOUNDOK; - } - - if (catweasel) - { - #ifdef __WIN32__ - catweaselhandle = CreateFile("\\\\.\\SID6581_1", GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ, 0L, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0L); - if (catweaselhandle == INVALID_HANDLE_VALUE) - return 0; - #else - catweaselfd = open("/dev/sid", O_WRONLY); - if (catweaselfd < 0) - catweaselfd = open("/dev/misc/sid", O_WRONLY); - if (catweaselfd < 0) - return 0; - #ifndef __amigaos__ - if (ntsc) - ioctl(catweaselfd, CWSID_IOCTL_NTSC); - else - ioctl(catweaselfd, CWSID_IOCTL_PAL); - #endif - #endif - - usecatweasel = 1; - timer = SDL_AddTimer(1000 / framerate, sound_timer, NULL); - goto SOUNDOK; - } - #ifdef USE_EXSID if (exsid) { @@ -265,15 +130,13 @@ int sound_init(unsigned mr, unsigned writer, unsigned hardsid, unsigned m, unsig snd_player = &sound_playrout; snd_setcustommixer(sound_mixer); - SOUNDOK: +SOUNDOK: initted = 1; return 1; } void sound_uninit(void) { - int c; - if (!initted) return; initted = 0; @@ -281,9 +144,9 @@ void sound_uninit(void) // not mixing stuff anymore, and we can safely delete related structures SDL_Delay(50); - if (usehardsid || usecatweasel || useexsid) + if (useexsid) { - #ifdef __WIN32__ +#ifdef __WIN32__ if (!playerthread) { SDL_RemoveTimer(timer); @@ -294,9 +157,9 @@ void sound_uninit(void) SDL_WaitThread(playerthread, NULL); playerthread = NULL; } - #else +#else SDL_RemoveTimer(timer); - #endif +#endif } else { @@ -309,66 +172,13 @@ void sound_uninit(void) fclose(writehandle); writehandle = NULL; } - + if (buffer) { free(buffer); buffer = NULL; } - if (usehardsid) - { - #ifdef __WIN32__ - for (c = 0; c < NUMSIDREGS; c++) - { - if (cycleexacthardsid) { - HardSID_Write(usehardsid-1, SIDWRITEDELAY, c, 0x00); - } - else { - WriteToHardSID(usehardsid-1, c, 0x00); - } - } - MuteHardSID_Line(TRUE); - #else - if (hardsidfd >= 0) - { - for (c = 0; c < NUMSIDREGS; c++) - { - Uint32 dataword = c << 8; - write(hardsidfd, &dataword, 4); - } - close(hardsidfd); - hardsidfd = -1; - } - #endif - } - - if (usecatweasel) - { - #ifdef __WIN32__ - DWORD w; - unsigned char buf[NUMSIDREGS * 2]; - for (w = 0; w < NUMSIDREGS; w++) - { - buf[w*2] = 0x18 - w; - buf[w*2+1] = 0; - } - DeviceIoControl(catweaselhandle, SID_SID_PEEK_POKE, buf, sizeof(buf), 0L, 0UL, &w, 0L); - CloseHandle(catweaselhandle); - catweaselhandle = INVALID_HANDLE_VALUE; - #else - if (catweaselfd >= 0) - { - unsigned char buf[NUMSIDREGS]; - memset(buf, 0, sizeof(buf)); - lseek(catweaselfd, 0, SEEK_SET); - write(catweaselfd, buf, sizeof(buf)); - close(catweaselfd); - catweaselfd = -1; - } - #endif - } - #ifdef USE_EXSID if (useexsid) { @@ -414,136 +224,12 @@ Uint32 sound_timer(void *userdata, SDL_TimerID timerID, Uint32 interval) return interval; } -#ifdef __WIN32__ -int sound_thread(void *userdata) -{ - unsigned long flush_cycles_interactive = hardsidbufinteractive * 1000; /* 0 = flush off for interactive mode*/ - unsigned long flush_cycles_playback = hardsidbufplayback * 1000; /* 0 = flush off for playback mode*/ - unsigned long cycles_after_flush = 0; - boolean interactive; - - while (runplayerthread) - { - unsigned cycles = 1000000 / framerate; // HardSID should be clocked at 1MHz - int c; - - if (flush_cycles_interactive > 0 || flush_cycles_playback > 0) - { - cycles_after_flush += cycles; - } - - // Do flush if starting playback, stopping playback, starting an interactive note etc. - if (flushplayerthread) - { - SDL_LockMutex(flushmutex); - if (HardSID_Flush) - { - HardSID_Flush(usehardsid-1); - } - // Can clear player suspend now (if set) - suspendplayroutine = FALSE; - flushplayerthread = FALSE; - SDL_UnlockMutex(flushmutex); - - SDL_Delay(0); - } - - if (!suspendplayroutine) playroutine(); - - interactive = !(boolean)recordmode /* jam mode */ || !(boolean)isplaying(); - - for (c = 0; c < NUMSIDREGS; c++) - { - unsigned o = sid_getorder(c); - - HardSID_Write(usehardsid-1, SIDWRITEDELAY, o, sidreg[o]); - cycles -= SIDWRITEDELAY; - } - - // Now wait the rest of frame - while (cycles) - { - unsigned runnow = cycles; - if (runnow > 65535) runnow = 65535; - HardSID_Delay(usehardsid-1, runnow); - cycles -= runnow; - } - - if ((flush_cycles_interactive>0 && interactive && cycles_after_flush>=flush_cycles_interactive) || - (flush_cycles_playback>0 && !interactive && cycles_after_flush>=flush_cycles_playback)) - { - if (HardSID_SoftFlush) - HardSID_SoftFlush(usehardsid-1); - cycles_after_flush = 0; - } - } - - unsigned r; - - for (r = 0; r < NUMSIDREGS; r++) - { - HardSID_Write(usehardsid-1, SIDWRITEDELAY, r, 0); - } - if (HardSID_SoftFlush) - HardSID_SoftFlush(usehardsid-1); - - return 0; -} -#endif - void sound_playrout(void) { - int c; - playroutine(); - if (usehardsid) - { - #ifdef __WIN32__ - for (c = 0; c < NUMSIDREGS; c++) - { - unsigned o = sid_getorder(c); - if (cycleexacthardsid) { - HardSID_Write(usehardsid-1, SIDWRITEDELAY, o, sidreg[o]); - } - else { - WriteToHardSID(usehardsid-1, o, sidreg[o]); - } - } - #else - for (c = 0; c < NUMSIDREGS; c++) - { - unsigned o = sid_getorder(c); - Uint32 dataword = (o << 8) | sidreg[o]; - write(hardsidfd, &dataword, 4); - } - #endif - } - else if (usecatweasel) - { - #ifdef __WIN32__ - DWORD w; - unsigned char buf[NUMSIDREGS * 2]; - - for(w = 0; w < NUMSIDREGS; w++) - { - unsigned o = sid_getorder(w); - - buf[w*2] = o; - buf[w*2+1] = sidreg[o]; - } - DeviceIoControl(catweaselhandle, SID_SID_PEEK_POKE, buf, sizeof(buf), 0L, 0UL, &w, 0L); - #else - for (c = 0; c < NUMSIDREGS; c++) - { - unsigned o = sid_getorder(c); - lseek(catweaselfd, o, SEEK_SET); - write(catweaselfd, &sidreg[o], 1); - } - #endif - } #ifdef USE_EXSID - else if (useexsid) + if (useexsid) { exSID_delay(exsidfd, exsidDelay); for (c = 0; c < NUMSIDREGS; c++) @@ -572,29 +258,3 @@ void sound_mixer(Sint32 *dest, unsigned samples) for (c = snd_channels; c; c--) *dest++ = buffer[s]; } - -#ifdef __WIN32__ -void InitHardDLL() -{ - if (!(hardsiddll=LoadLibrary("HARDSID.DLL"))) return; - - WriteToHardSID = (lpWriteToHardSID) (void (*)(void)) GetProcAddress(hardsiddll, "WriteToHardSID"); - ReadFromHardSID = (lpReadFromHardSID) (void (*)(void)) GetProcAddress(hardsiddll, "ReadFromHardSID"); - InitHardSID_Mapper = (lpInitHardSID_Mapper) (void (*)(void)) GetProcAddress(hardsiddll, "InitHardSID_Mapper"); - MuteHardSID_Line = (lpMuteHardSID_Line) (void (*)(void)) GetProcAddress(hardsiddll, "MuteHardSID_Line"); - - if (!WriteToHardSID) return; - - // Try to get cycle-exact interface - HardSID_Delay = (lpHardSID_Delay) (void (*)(void)) GetProcAddress(hardsiddll, "HardSID_Delay"); - HardSID_Write = (lpHardSID_Write) (void (*)(void)) GetProcAddress(hardsiddll, "HardSID_Write"); - HardSID_Flush = (lpHardSID_Flush) (void (*)(void)) GetProcAddress(hardsiddll, "HardSID_Flush"); - HardSID_SoftFlush = (lpHardSID_SoftFlush) (void (*)(void)) GetProcAddress(hardsiddll, "HardSID_SoftFlush"); - HardSID_Lock = (lpHardSID_Lock) (void (*)(void)) GetProcAddress(hardsiddll, "HardSID_Lock"); - if ((HardSID_Delay) && (HardSID_Write) && (HardSID_Flush) && (HardSID_SoftFlush) && (HardSID_Lock)) - cycleexacthardsid = TRUE; - - InitHardSID_Mapper(); - dll_initialized = TRUE; -} -#endif diff --git a/src/gsound.h b/src/gsound.h index 955347f..98db92a 100644 --- a/src/gsound.h +++ b/src/gsound.h @@ -1,19 +1,6 @@ #ifndef GSOUND_H #define GSOUND_H -#ifdef GSOUND_C - -#ifdef __WIN32__ -#include -#else -#include -#include -#include -#include "cwsid.h" -#endif - -#endif - #define MINMIXRATE 11025 #define MAXMIXRATE 48000 #define DEFAULTMIXRATE 48000 @@ -25,7 +12,7 @@ #define MIXBUFFERSIZE 65536 -int sound_init(unsigned mr, unsigned writer, unsigned hardsid, unsigned m, unsigned ntsc, unsigned multiplier, unsigned catweasel, unsigned interpolate, unsigned customclockrate, unsigned exsid, float filterbias, unsigned combwaves); +int sound_init(unsigned mr, unsigned writer, unsigned m, unsigned ntsc, unsigned multiplier, unsigned interpolate, unsigned customclockrate, unsigned exsid, float filterbias, unsigned combwaves); void sound_uninit(void); void sound_suspend(void); void sound_flush(void); diff --git a/src/gt2reloc.c b/src/gt2reloc.c index 5177b39..fd627ae 100644 --- a/src/gt2reloc.c +++ b/src/gt2reloc.c @@ -57,12 +57,8 @@ unsigned customclockrate = 0; unsigned usefinevib = 0; unsigned mr = DEFAULTMIXRATE; unsigned writer = 0; -unsigned hardsid = 0; -unsigned catweasel = 0; unsigned interpolate = 0; unsigned residdelay = 0; -unsigned hardsidbufinteractive = 20; -unsigned hardsidbufplayback = 400; float basepitch = 0.0f; char configbuf[MAX_PATHNAME]; From 446c8c71ab1b60dcdb256e675827e44b1ec944b2 Mon Sep 17 00:00:00 2001 From: Leandro Nini Date: Sun, 5 Jul 2026 11:03:04 +0200 Subject: [PATCH 04/15] Apply changes from fork https://github.com/jansalleine/gt2fork/commit/8690d7e57a33dd92cce3bb0bae8c830dbc219115 https://github.com/jansalleine/gt2fork/commit/36f64a9d46222fb91e0908ff915f41f96584484d --- CMakeLists.txt | 4 ++ src/goattrk2.c | 18 ++++---- src/gsid.cpp | 112 ++++++++++++++++++++++++++++++++++++++++++++++++- src/gsid.h | 8 +++- src/gsound.c | 26 ++++++++++-- src/gsound.h | 5 ++- 6 files changed, 157 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fad2437..2def8c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,10 @@ set(CMAKE_C_EXTENSIONS ON) set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR diff --git a/src/goattrk2.c b/src/goattrk2.c index 119774a..9f3acab 100644 --- a/src/goattrk2.c +++ b/src/goattrk2.c @@ -410,7 +410,7 @@ int main(int argc, char **argv) clearsong(1,1,1,1,1); // Init sound - if (!sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves)) + if (!sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, numsids, exsid, filterbias, combwaves)) { printtextc(MAX_ROWS/2-1,15,"Sound init failed. Press any key to run without sound (notice that song timer won't start)"); waitkeynoupdate(); @@ -638,8 +638,8 @@ void mousecommands(void) for (c = 0; c < MAX_CHN; c++) { if ((mousey == dpos.patternsY) && - (mousex >= dpos.patternsX + 11 + c*13) && - (mousex <= dpos.patternsX + 12 + c*13)) + (mousex >= dpos.patternsX + 10 + c*13) && + (mousex <= dpos.patternsX + 11 + c*13)) { if ((!prevmouseb) || (mouseheld > HOLDDELAY)) { @@ -660,7 +660,7 @@ void mousecommands(void) if ((mousey >= dpos.patternsY) && (mousey <= dpos.statusBottomY - 1) && (mousex >= dpos.patternsX + 3 + c*13) && - (mousex <= dpos.patternsX + 12 + c*13)) + (mousex <= dpos.patternsX + 11 + c*13)) { int x = mousex-(dpos.patternsX + 3)-c*13; int newpos = mousey-(dpos.patternsY+1)+epview; @@ -883,12 +883,12 @@ void mousecommands(void) if ((mousex >= dpos.statusTopFvX+9) && (mousex <= dpos.statusTopFvX+12)) { ntsc ^= 1; - sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves); + sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, numsids, exsid, filterbias, combwaves); } if ((mousex >= dpos.statusTopFvX+14) && (mousex <= dpos.statusTopFvX+17)) { sidmodel ^= 1; - sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves); + sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, numsids, exsid, filterbias, combwaves); } if ((mousex >= dpos.statusTopFvX+22) && (mousex <= dpos.statusTopFvX+25)) editadsr(); @@ -1113,7 +1113,7 @@ void generalcommands(void) else { sidmodel ^= 1; - sound_init( mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves); + sound_init( mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, numsids, exsid, filterbias, combwaves); } break; @@ -1488,7 +1488,7 @@ void prevmultiplier(void) if (multiplier > 0) { multiplier--; - sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves); + sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, numsids, exsid, filterbias, combwaves); } } @@ -1497,7 +1497,7 @@ void nextmultiplier(void) if (multiplier < 16) { multiplier++; - sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves); + sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, numsids, exsid, filterbias, combwaves); } } diff --git a/src/gsid.cpp b/src/gsid.cpp index e63afa3..34f1a7e 100644 --- a/src/gsid.cpp +++ b/src/gsid.cpp @@ -14,6 +14,7 @@ int clockrate; int samplerate; unsigned char sidreg[NUMSIDREGS]; +unsigned char sidreg2[NUMSIDREGS]; unsigned char sidorder[] = {0x15,0x16,0x18,0x17, 0x05,0x06,0x02,0x03,0x00,0x01,0x04, @@ -27,11 +28,15 @@ unsigned char altsidorder[] = 0x12,0x0e,0x0f,0x10,0x11,0x13,0x14}; reSIDfp::residfp *sid = nullptr; +reSIDfp::residfp *sid2 = nullptr; extern unsigned residdelay; extern unsigned adparam; -void sid_init(int speed, unsigned m, unsigned ntsc, unsigned interpolate, unsigned customclockrate, float filterbias, unsigned combwaves) +void sid_init(int speed, unsigned m, + unsigned ntsc, unsigned interpolate, + unsigned customclockrate, unsigned numsids, + float filterbias, unsigned combwaves) { if (ntsc) clockrate = NTSCCLOCKRATE; else clockrate = PALCLOCKRATE; @@ -42,35 +47,47 @@ void sid_init(int speed, unsigned m, unsigned ntsc, unsigned interpolate, unsign samplerate = speed; if (!sid) sid = new reSIDfp::residfp; + if (numsids == 2 && !sid2) sid2 = new reSIDfp::residfp; switch(interpolate) { case 0: sid->setSamplingParameters(clockrate, reSIDfp::DECIMATE, speed); + if (sid2) sid2->setSamplingParameters(clockrate, reSIDfp::DECIMATE, speed); break; default: case 1: sid->setSamplingParameters(clockrate, reSIDfp::RESAMPLE, speed); + if (sid2) sid2->setSamplingParameters(clockrate, reSIDfp::RESAMPLE, speed); break; } sid->reset(); sid->setFilter6581Curve(filterbias); sid->setFilter8580Curve(filterbias); + if (sid2) + { + sid2->reset(); + sid2->setFilter6581Curve(filterbias); + sid2->setFilter8580Curve(filterbias); + } switch(combwaves) { case 0: sid->setCombinedWaveforms(reSIDfp::WEAK); + if (sid2) sid2->setCombinedWaveforms(reSIDfp::WEAK); break; default: case 1: sid->setCombinedWaveforms(reSIDfp::AVERAGE); + if (sid2) sid2->setCombinedWaveforms(reSIDfp::AVERAGE); break; case 2: sid->setCombinedWaveforms(reSIDfp::STRONG); + if (sid2) sid2->setCombinedWaveforms(reSIDfp::STRONG); break; } @@ -78,14 +95,17 @@ void sid_init(int speed, unsigned m, unsigned ntsc, unsigned interpolate, unsign for (int c = 0; c < NUMSIDREGS; c++) { sidreg[c] = 0x00; + sidreg2[c] = 0x00; } if (m == 1) { sid->setChipModel(reSIDfp::CSG8580); + if (sid2) sid2->setChipModel(reSIDfp::CSG8580); } else { sid->setChipModel(reSIDfp::MOS6581); + if (sid2) sid2->setChipModel(reSIDfp::MOS6581); } } @@ -157,3 +177,93 @@ int sid_fillbuffer(short *ptr, int samples) return total; } + +int sid_fillbuffer_stereo(short *lptr, short *rptr, int samples) +{ + if (!sid || !sid2) + return 0; + + int tdelta2; + int result = 0; + int total = 0; + + int badline = rand() % NUMSIDREGS; + + int tdelta = clockrate * samples / samplerate; + if (tdelta <= 0) return total; + + for (int c = 0; c < NUMSIDREGS; c++) + { + unsigned char o = sid_getorder(c); + + // Extra delay for loading the waveform (and mt_chngate,x) + if ((o == 4) || (o == 11) || (o == 18)) + { + tdelta2 = SIDWAVEDELAY; + result = sid->clock(tdelta2, lptr); + tdelta2 = SIDWAVEDELAY; + sid2->clock(tdelta2, rptr); + + total += result; + lptr += result; + rptr += result; + samples -= result; + tdelta -= SIDWAVEDELAY; + } + + // Possible random badline delay once per writing + if ((badline == c) && (residdelay)) + { + tdelta2 = residdelay; + result = sid->clock(tdelta2, lptr); + tdelta2 = residdelay; + result = sid2->clock(tdelta2, rptr); + total += result; + lptr += result; + rptr += result; + samples -= result; + tdelta -= residdelay; + } + + sid->write(o, sidreg[o]); + sid2->write(o, sidreg2[o]); + + tdelta2 = SIDWRITEDELAY-5; + result = sid->clock(tdelta2, lptr); + tdelta2 = SIDWRITEDELAY-5; + result = sid2->clock(tdelta2, rptr); + total += result; + lptr += result; + rptr += result; + samples -= result; + tdelta -= SIDWRITEDELAY; + + if (tdelta <= 0) return total; + } + + tdelta2 = tdelta; + result = sid->clock(tdelta, lptr); + tdelta2 = tdelta; + result = sid2->clock(tdelta, rptr); + total += result; + lptr += result; + rptr += result; + samples -= result; + + // Loop extra cycles until all samples produced + while (samples) + { + tdelta = clockrate * samples / samplerate; + if (tdelta <= 0) return total; + + result = sid->clock(tdelta, lptr); + tdelta = clockrate * samples / samplerate; + result = sid2->clock(tdelta, rptr); + total += result; + lptr += result; + rptr += result; + samples -= result; + } + + return total; +} diff --git a/src/gsid.h b/src/gsid.h index 66bb820..9ea401b 100644 --- a/src/gsid.h +++ b/src/gsid.h @@ -3,17 +3,23 @@ #define NUMSIDREGS 0x19 #define SIDWRITEDELAY 14 // lda $xxxx,x 4 cycles, sta $d400,x 5 cycles, dex 2 cycles, bpl 3 cycles +#define SIDWAVEDELAY 4 // and $xxxx,x 4 cycles extra #ifdef __cplusplus extern "C" { #endif -void sid_init(int speed, unsigned m, unsigned ntsc, unsigned interpolate, unsigned customclockrate, float filterbias, unsigned combwaves); +void sid_init(int speed, unsigned m, + unsigned ntsc, unsigned interpolate, + unsigned customclockrate, unsigned numsids, + float filterbias, unsigned combwaves); int sid_fillbuffer(short *ptr, int samples); +int sid_fillbuffer_stereo(short *lptr, short *rptr, int samples); unsigned char sid_getorder(unsigned char index); #ifndef GSID_C extern unsigned char sidreg[NUMSIDREGS]; +extern unsigned char sidreg2[NUMSIDREGS]; #endif #ifdef __cplusplus diff --git a/src/gsound.c b/src/gsound.c index 9f8c497..b765f56 100644 --- a/src/gsound.c +++ b/src/gsound.c @@ -21,6 +21,8 @@ int initted = 0; int firsttimeinit = 1; unsigned framerate = PALFRAMERATE; Sint16 *buffer = NULL; +Sint16 *lbuffer = NULL; +Sint16 *rbuffer = NULL; FILE *writehandle = NULL; SDL_TimerID timer = 0; @@ -34,7 +36,8 @@ unsigned exsidDelay = 0; #endif int sound_init(unsigned mr, unsigned writer, unsigned m, unsigned ntsc, - unsigned multiplier, unsigned interpolate, unsigned customclockrate, + unsigned multiplier, unsigned interpolate, + unsigned customclockrate, unsigned numsids, unsigned exsid, float filterbias, unsigned combwaves) { #ifdef __WIN32__ @@ -110,7 +113,9 @@ int sound_init(unsigned mr, unsigned writer, unsigned m, unsigned ntsc, #endif if (!buffer) buffer = (Sint16*)malloc(MIXBUFFERSIZE * sizeof(Sint16)); - if (!buffer) return 0; + if (!lbuffer) lbuffer = (Sint16*)malloc(MIXBUFFERSIZE * sizeof(Sint16)); + if (!rbuffer) rbuffer = (Sint16*)malloc(MIXBUFFERSIZE * sizeof(Sint16)); + if ((!buffer) || (!lbuffer) || (!rbuffer)) return 0; if (writer) writehandle = fopen("sidaudio.raw", "wb"); @@ -121,11 +126,12 @@ int sound_init(unsigned mr, unsigned writer, unsigned m, unsigned ntsc, if (firsttimeinit) { - if (!snd_init(mr, SIXTEENBIT|MONO, 1, 0)) return 0; + if (numsids == 1 && !snd_init(mr, SIXTEENBIT|MONO, 1, 0)) return 0; + else if (numsids == 2 && !snd_init(mr, SIXTEENBIT|STEREO, 1, 0)) return 0; firsttimeinit = 0; } playspeed = snd_mixrate; - sid_init(playspeed, m, ntsc, interpolate, customclockrate, filterbias, combwaves); + sid_init(playspeed, m, ntsc, interpolate, customclockrate, numsids, filterbias, combwaves); snd_player = &sound_playrout; snd_setcustommixer(sound_mixer); @@ -179,6 +185,18 @@ void sound_uninit(void) buffer = NULL; } + if (lbuffer) + { + free(lbuffer); + lbuffer = NULL; + } + + if (rbuffer) + { + free(rbuffer); + rbuffer = NULL; + } + #ifdef USE_EXSID if (useexsid) { diff --git a/src/gsound.h b/src/gsound.h index 98db92a..5d1ead4 100644 --- a/src/gsound.h +++ b/src/gsound.h @@ -12,7 +12,10 @@ #define MIXBUFFERSIZE 65536 -int sound_init(unsigned mr, unsigned writer, unsigned m, unsigned ntsc, unsigned multiplier, unsigned interpolate, unsigned customclockrate, unsigned exsid, float filterbias, unsigned combwaves); +int sound_init(unsigned mr, unsigned writer, unsigned m, unsigned ntsc, + unsigned multiplier, unsigned interpolate, + unsigned customclockrate, unsigned numsids, + unsigned exsid, float filterbias, unsigned combwaves); void sound_uninit(void); void sound_suspend(void); void sound_flush(void); From 848c843b8096f7e3eef9c888804b2f85be14b1d6 Mon Sep 17 00:00:00 2001 From: Leandro Nini Date: Sun, 5 Jul 2026 13:04:50 +0200 Subject: [PATCH 05/15] Apply changes from fork https://github.com/jansalleine/gt2fork/commit/a35c9a38f880ab9c54b8f748d0bea0e3a01385e9 https://github.com/jansalleine/gt2fork/commit/b9be3232813cc4ac42a47b7de5aa491c6d556df3 https://github.com/jansalleine/gt2fork/commit/97d8ea08943299888b22bdf82e90156a2d871ee8 --- src/gcommon.h | 1 + src/gconsole.c | 18 ++++++++++++++- src/gconsole.h | 1 + src/gdisplay.c | 29 +++++++++++++++++++---- src/goattrk2.c | 49 +++++++++++++++++++++++++++------------ src/goattrk2.h | 1 + src/gpattern.c | 24 +++++++++++-------- src/gplay.c | 10 +++++--- src/greloc.c | 22 ++++++++++++------ src/gsound.c | 62 ++++++++++++++++++++++++++++++++++++++------------ src/gsound.h | 3 +-- src/gt2reloc.c | 3 +++ 12 files changed, 167 insertions(+), 56 deletions(-) diff --git a/src/gcommon.h b/src/gcommon.h index bd94964..1b46ff9 100644 --- a/src/gcommon.h +++ b/src/gcommon.h @@ -27,6 +27,7 @@ #define MAX_STR 32 #define MAX_INSTR 64 #define MAX_CHN 3 +#define MAX_CHN_MONO 3 #define MAX_PATT 208 #define MAX_TABLES 4 #define MAX_TABLELEN 255 diff --git a/src/gconsole.c b/src/gconsole.c index 40319eb..047d49e 100644 --- a/src/gconsole.c +++ b/src/gconsole.c @@ -73,7 +73,7 @@ int initscreen(void) unsigned xsize = MAX_COLUMNS * 8; unsigned ysize = MAX_ROWS * 16; - printf("xsize: %d, ysize: %d", xsize, ysize); + printf("xsize: %d, ysize: %d\n", xsize, ysize); if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) return 0; @@ -494,3 +494,19 @@ void getkey(void) if (rawkey == SDL_SCANCODE_KP_8) key = '8'; if (rawkey == SDL_SCANCODE_KP_9) key = '9'; } + +void initDisplayPositions(void) +{ + if (numsids == 1) + { + dpos.channelsX = MAX_COLUMNS-21; + dpos.orderlistX = 54; + dpos.patternsX = 14; + } + else if (numsids == 2) + { + dpos.channelsX = MAX_COLUMNS-42; + dpos.orderlistX = 80; + dpos.patternsX = 1; + } +} diff --git a/src/gconsole.h b/src/gconsole.h index d6693e0..493240f 100644 --- a/src/gconsole.h +++ b/src/gconsole.h @@ -41,6 +41,7 @@ void printblankc(int x, int y, int color, int length); void drawbox(int x, int y, int color, int sx, int sy); void printbg(int x, int y, int color, int length); void getkey(void); +void initDisplayPositions(void); #ifndef GCONSOLE_C extern int key, rawkey, shiftpressed, cursorflashdelay; diff --git a/src/gdisplay.c b/src/gdisplay.c index e0dc7f9..c21a583 100644 --- a/src/gdisplay.c +++ b/src/gdisplay.c @@ -63,6 +63,8 @@ void printstatus(void) int c, d, color, color2; int cc = cursorcolortable[cursorflash]; int visibleOrderlist = VISIBLEORDERLIST; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; menu = 0; if ((mouseb > MOUSEB_LEFT) && (mousey <= 1) && (!eamode)) menu = 1; @@ -117,7 +119,7 @@ void printstatus(void) if ((followplay) && (isplaying())) { - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { int newpos = chn[c].pattptr / 4; if (chn[c].advance) epnum[c] = chn[c].pattnum; @@ -150,7 +152,7 @@ void printstatus(void) } } - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { sprintf(textbuffer, "CH."); printtext(dpos.patternsX+c*13, dpos.patternsY, colors.CTITLE, textbuffer); @@ -268,7 +270,7 @@ void printstatus(void) sprintf(textbuffer, ")"); printtext(dpos.orderlistX+33, dpos.orderlistY, colors.CTITLE, textbuffer); - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { sprintf(textbuffer, " %d ", c+1); printtext(dpos.orderlistX, dpos.orderlistY+1+c, colors.CTITLE, textbuffer); @@ -534,8 +536,25 @@ void printstatus(void) printtext(dpos.octaveX+10, dpos.octaveY+1, colors.CEDIT, textbuffer); - printtext(dpos.channelsX, dpos.channelsY, colors.CTITLE, " CHN1 CHN2 CHN3 "); - for (c = 0; c < MAX_CHN; c++) + if (numsids == 1) + { + printtext( + dpos.channelsX, + dpos.channelsY, + colors.CTITLE, + " CHN1 CHN2 CHN3 " + ); + } + else if (numsids == 2) + { + printtext( + dpos.channelsX, + dpos.channelsY, + colors.CTITLE, + " CHN1 CHN2 CHN3 CHN4 CHN5 CHN6 " + ); + } + for (c = 0; c < maxChns; c++) { int chnpos = chn[c].songptr; int chnrow = chn[c].pattptr/4; diff --git a/src/goattrk2.c b/src/goattrk2.c index 9f3acab..bf12fcf 100644 --- a/src/goattrk2.c +++ b/src/goattrk2.c @@ -62,13 +62,14 @@ unsigned writer = 0; unsigned exsid = 0; unsigned interpolate = 1; unsigned residdelay = 0; +unsigned monomode = 0; +unsigned numsids = 1; unsigned combwaves = 1; float basepitch = 0.0f; float filterbias = 0.5f; float equaldivisionsperoctave = 12.0f; int tuningcount = 0; double tuning[96]; -unsigned numsids = 1; char configbuf[MAX_PATHNAME]; char loadedsongfilename[MAX_FILENAME]; @@ -175,6 +176,7 @@ int main(int argc, char **argv) getparam(configfile, (unsigned *)&zeropageadr); getparam(configfile, &playerversion); getparam(configfile, &keypreset); + getparam(configfile, &defaultpatternlength); getparam(configfile, (unsigned *)&stepsize); getparam(configfile, &multiplier); getparam(configfile, &adparam); @@ -378,11 +380,15 @@ int main(int argc, char **argv) if (optimizerealtime > 1) optimizerealtime = 1; if (residdelay > 63) residdelay = 63; if (customclockrate < 100) customclockrate = 0; + if (defaultpatternlength < 1) defaultpatternlength = 1; + if (defaultpatternlength > MAX_PATTROWS) defaultpatternlength = MAX_PATTROWS; if (combwaves < 0) combwaves = 0; else if (combwaves > 2) combwaves = 2; if (filterbias < 0.0) filterbias = 0.0; else if (filterbias > 1.0) filterbias = 1.0; + initDisplayPositions(); + // Read Scala tuning file if (scalatuningfilepath[0] != '0' && scalatuningfilepath[1] != '\0') { @@ -410,7 +416,7 @@ int main(int argc, char **argv) clearsong(1,1,1,1,1); // Init sound - if (!sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, numsids, exsid, filterbias, combwaves)) + if (!sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves)) { printtextc(MAX_ROWS/2-1,15,"Sound init failed. Press any key to run without sound (notice that song timer won't start)"); waitkeynoupdate(); @@ -466,6 +472,7 @@ int main(int argc, char **argv) ";Packer/relocator zeropage baseaddress\n$%02x\n\n" ";Packer/relocator player type (0 = standard ... 3 = minimal)\n%d\n\n" ";Key entry mode (0 = Protracker, 1 = DMC, 2 = Janko)\n%d\n\n" + ";Pattern default size (default = 32 / $20)\n%d\n\n" ";Pattern highlight step size\n%d\n\n" ";Speed multiplier (0 = 25Hz, 1 = 1X, 2 = 2X etc.)\n%d\n\n" ";Hardrestart ADSR parameter\n$%04x\n\n" @@ -494,6 +501,7 @@ int main(int argc, char **argv) zeropageadr, playerversion, keypreset, + defaultpatternlength, stepsize, multiplier, adparam, @@ -631,11 +639,13 @@ void docommand(void) void mousecommands(void) { int c; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; if (!mouseb) return; // Pattern editpos & pattern number selection - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { if ((mousey == dpos.patternsY) && (mousex >= dpos.patternsX + 10 + c*13) && @@ -708,7 +718,7 @@ void mousecommands(void) // Song editpos & songnumber selection if ((mousey >= dpos.orderlistY) && - (mousey <= dpos.orderlistY + MAX_CHN + 2) && + (mousey <= dpos.orderlistY + maxChns + 2) && (mousex >= dpos.orderlistX)) { int newpos = esview + (mousex-(dpos.orderlistX+4)) / 3; @@ -799,9 +809,9 @@ void mousecommands(void) for (c = 0; c < MAX_TABLES; c++) { if ((mousey >= dpos.instrumentsY+7) && - (mousey <= dpos.instrumentsY+8+VISIBLETABLEROWS-1) && + (mousey <= dpos.instrumentsY+8+VISIBLETABLEROWS) && (mousex >= dpos.instrumentsX+3+c*10) && - (mousex <= dpos.instrumentsX+7+10+c*10)) + (mousex <= dpos.instrumentsX+7+c*10)) { int newpos = mousey-(dpos.instrumentsY+7)+etview[etnum]; if (newpos < 0) newpos = 0; @@ -854,7 +864,7 @@ void mousecommands(void) { recordmode ^= 1; } - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { if ((!prevmouseb) && (mousey >= dpos.channelsY) && @@ -883,12 +893,12 @@ void mousecommands(void) if ((mousex >= dpos.statusTopFvX+9) && (mousex <= dpos.statusTopFvX+12)) { ntsc ^= 1; - sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, numsids, exsid, filterbias, combwaves); + sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves); } if ((mousex >= dpos.statusTopFvX+14) && (mousex <= dpos.statusTopFvX+17)) { sidmodel ^= 1; - sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, numsids, exsid, filterbias, combwaves); + sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves); } if ((mousex >= dpos.statusTopFvX+22) && (mousex <= dpos.statusTopFvX+25)) editadsr(); @@ -940,6 +950,8 @@ void mousecommands(void) void generalcommands(void) { int c; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; switch(key) { @@ -992,7 +1004,7 @@ void generalcommands(void) break; case ';': - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { if (espos[c]) espos[c]--; if (espos[c] < esview) @@ -1006,7 +1018,7 @@ void generalcommands(void) break; case ':': - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { if (espos[c] < songlen[esnum][c]-1) espos[c]++; @@ -1113,12 +1125,19 @@ void generalcommands(void) else { sidmodel ^= 1; - sound_init( mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, numsids, exsid, filterbias, combwaves); + sound_init( mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves); } break; case KEY_F9: - relocator(); + if (!shiftpressed) + { + relocator(); + } + else if (numsids == 2) + { + monomode ^= 1; + } break; case KEY_F10: @@ -1488,7 +1507,7 @@ void prevmultiplier(void) if (multiplier > 0) { multiplier--; - sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, numsids, exsid, filterbias, combwaves); + sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves); } } @@ -1497,7 +1516,7 @@ void nextmultiplier(void) if (multiplier < 16) { multiplier++; - sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, numsids, exsid, filterbias, combwaves); + sound_init(mr, writer, sidmodel, ntsc, multiplier, interpolate, customclockrate, exsid, filterbias, combwaves); } } diff --git a/src/goattrk2.h b/src/goattrk2.h index d1e3531..254d5cd 100644 --- a/src/goattrk2.h +++ b/src/goattrk2.h @@ -77,6 +77,7 @@ extern unsigned writer; extern unsigned exsid; extern unsigned interpolate; extern unsigned numsids; +extern unsigned monomode; extern float basepitch; extern char configbuf[MAX_PATHNAME]; extern char loadedsongfilename[MAX_FILENAME]; diff --git a/src/gpattern.c b/src/gpattern.c index 8d067fa..16ae099 100644 --- a/src/gpattern.c +++ b/src/gpattern.c @@ -73,6 +73,8 @@ void patterncommands(void) { size_t i; int c, scrrep; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; switch(key) { @@ -886,7 +888,7 @@ void patterncommands(void) { int c; - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { if (eseditpos < songlen[esnum][c]) espos[c] = eseditpos; if (esend[c] <= espos[c]) esend[c] = 0; @@ -907,7 +909,7 @@ void patterncommands(void) { epcolumn = 0; epchn++; - if (epchn >= MAX_CHN) epchn = 0; + if (epchn >= maxChns) epchn = 0; if (eppos > pattlen[epnum[epchn]]) eppos = pattlen[epnum[epchn]]; } } @@ -930,7 +932,7 @@ void patterncommands(void) { epcolumn = 5; epchn--; - if (epchn < 0) epchn = MAX_CHN-1; + if (epchn < 0) epchn = maxChns-1; if (eppos > pattlen[epnum[epchn]]) eppos = pattlen[epnum[epchn]]; } } @@ -975,17 +977,17 @@ void patterncommands(void) if (!shiftpressed) { epchn++; - if (epchn >= MAX_CHN) epchn = 0; + if (epchn >= maxChns) epchn = 0; if (eppos > pattlen[epnum[epchn]]) eppos = pattlen[epnum[epchn]]; } else { epchn--; - if (epchn < 0) epchn = MAX_CHN-1; + if (epchn < 0) epchn = maxChns-1; if (eppos > pattlen[epnum[epchn]]) eppos = pattlen[epnum[epchn]]; } break; - + case KEY_1: case KEY_2: case KEY_3: @@ -1201,10 +1203,12 @@ void splitpattern(void) int c = epnum[epchn]; int l = pattlen[c]; int d; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; if (eppos == 0) return; if (eppos == l) return; - + stopsong(); if (insertpattern(c)) @@ -1229,7 +1233,7 @@ void splitpattern(void) for (esnum = 0; esnum < MAX_SONGS; esnum++) { - for (eschn = 0; eschn < MAX_CHN; eschn++) + for (eschn = 0; eschn < maxChns; eschn++) { for (eseditpos = 0; eseditpos < songlen[esnum][eschn]; eseditpos++) { @@ -1251,6 +1255,8 @@ void joinpattern(void) { int c = epnum[epchn]; int d; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; if (eschn != epchn) return; if (songorder[esnum][epchn][eseditpos] != c) return; @@ -1292,7 +1298,7 @@ void joinpattern(void) for (esnum = 0; esnum < MAX_SONGS; esnum++) { - for (eschn = 0; eschn < MAX_CHN; eschn++) + for (eschn = 0; eschn < maxChns; eschn++) { for (eseditpos = 0; eseditpos < songlen[esnum][eschn]; eseditpos++) { diff --git a/src/gplay.c b/src/gplay.c index 000b3f9..e2e9431 100644 --- a/src/gplay.c +++ b/src/gplay.c @@ -52,11 +52,13 @@ void sequencer(int c, CHN *cptr); void initchannels(void) { int c; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; CHN *cptr = &chn[0]; memset(chn, 0, sizeof chn); - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { chn[c].trans = 0; chn[c].instr = 1; @@ -163,6 +165,8 @@ void playroutine(void) INSTR *iptr; CHN *cptr = &chn[0]; int c; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; if (songinit == PLAY_STOP) followplay = 0; @@ -182,7 +186,7 @@ void playroutine(void) songinit = 0x01; } - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { cptr->songptr = 0; cptr->command = 0; @@ -301,7 +305,7 @@ void playroutine(void) sidreg[0x17] = filterctrl; sidreg[0x18] = filtertype | masterfader; - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { iptr = &instr[cptr->instr]; diff --git a/src/greloc.c b/src/greloc.c index df431e7..4f51a0c 100644 --- a/src/greloc.c +++ b/src/greloc.c @@ -31,7 +31,8 @@ char *tablerightname[] = { "mt_filtspdtbl", "mt_speedrighttbl"}; -unsigned char chnused[MAX_CHN]; +unsigned char chnused[MAX_CHN_MONO]; +unsigned char chnused_stereo[MAX_CHN]; unsigned char pattused[MAX_PATT]; unsigned char pattmap[MAX_PATT]; unsigned char instrused[MAX_INSTR]; @@ -40,8 +41,10 @@ unsigned char tableused[MAX_TABLES][MAX_TABLELEN+1]; unsigned char tablemap[MAX_TABLES][MAX_TABLELEN+1]; int pattoffset[MAX_PATT]; int pattsize[MAX_PATT]; -int songoffset[MAX_SONGS][MAX_CHN]; -int songsize[MAX_SONGS][MAX_CHN]; +int songoffset[MAX_SONGS][MAX_CHN_MONO]; +int songsize[MAX_SONGS][MAX_CHN_MONO]; +int songoffset_stereo[MAX_SONGS][MAX_CHN]; +int songsize_stereo[MAX_SONGS][MAX_CHN]; int tableerror; int channels; int fixedparams; @@ -152,6 +155,7 @@ void relocator(void) unsigned char *instrwork = NULL; channels = 3; + //if (numsids == 2) channels = 6; fixedparams = 1; simplepulse = 1; firstnote = MAX_NOTES-1; @@ -193,6 +197,7 @@ void relocator(void) memset(pattused, 0, sizeof pattused); memset(instrused, 0, sizeof instrused); memset(chnused, 0, sizeof chnused); + memset(chnused_stereo, 0, sizeof chnused_stereo); memset(tableused, 0, sizeof tableused); memset(tablemap, 0, sizeof tablemap); tableerror = 0; @@ -200,6 +205,9 @@ void relocator(void) membuf_free(&src); membuf_free(&dest); + int maxChns = MAX_CHN; + //if (numsids == 1) maxChns = 3; + // Process song-orderlists countpatternlengths(); // Calculate amount of songs with nonzero length @@ -210,7 +218,7 @@ void relocator(void) (songlen[c][2])) { // See which patterns are used in this song - for (d = 0; d < MAX_CHN; d++) + for (d = 0; d < maxChns; d++) { songdatasize += songlen[c][d]+2; for (e = 0; e < songlen[c][d]; e++) @@ -659,7 +667,7 @@ void relocator(void) (songlen[c][1]) && (songlen[c][2])) { - for (d = 0; d < MAX_CHN; d++) + for (d = 0; d < maxChns; d++) { songoffset[c][d] = songdatasize; songsize[c][d] = songlen[c][d] + 2; @@ -702,7 +710,7 @@ void relocator(void) } else { - for (d = 0; d < MAX_CHN; d++) + for (d = 0; d < maxChns; d++) { songoffset[c][d] = songdatasize; songsize[c][d] = 0; @@ -1381,7 +1389,7 @@ void relocator(void) // Insert orderlists for (c = 0; c < songs; c++) { - for (d = 0; d < MAX_CHN; d++) + for (d = 0; d < maxChns; d++) { sprintf(textbuffer, "mt_song%d", c*3+d); insertlabel(textbuffer); diff --git a/src/gsound.c b/src/gsound.c index b765f56..0ce36f3 100644 --- a/src/gsound.c +++ b/src/gsound.c @@ -18,7 +18,6 @@ int playspeed; int useexsid = 0; int initted = 0; -int firsttimeinit = 1; unsigned framerate = PALFRAMERATE; Sint16 *buffer = NULL; Sint16 *lbuffer = NULL; @@ -36,8 +35,7 @@ unsigned exsidDelay = 0; #endif int sound_init(unsigned mr, unsigned writer, unsigned m, unsigned ntsc, - unsigned multiplier, unsigned interpolate, - unsigned customclockrate, unsigned numsids, + unsigned multiplier, unsigned interpolate, unsigned customclockrate, unsigned exsid, float filterbias, unsigned combwaves) { #ifdef __WIN32__ @@ -124,11 +122,13 @@ int sound_init(unsigned mr, unsigned writer, unsigned m, unsigned ntsc, if (playspeed < MINMIXRATE) playspeed = MINMIXRATE; if (playspeed > MAXMIXRATE) playspeed = MAXMIXRATE; - if (firsttimeinit) + if (numsids == 1 && !snd_init(mr, SIXTEENBIT|MONO, 1, 0)) { - if (numsids == 1 && !snd_init(mr, SIXTEENBIT|MONO, 1, 0)) return 0; - else if (numsids == 2 && !snd_init(mr, SIXTEENBIT|STEREO, 1, 0)) return 0; - firsttimeinit = 0; + return 0; + } + else if (numsids == 2 && !snd_init(mr, SIXTEENBIT|STEREO, 1, 0)) + { + return 0; } playspeed = snd_mixrate; sid_init(playspeed, m, ntsc, interpolate, customclockrate, numsids, filterbias, combwaves); @@ -266,13 +266,47 @@ void sound_mixer(Sint32 *dest, unsigned samples) if (!initted) return; if (samples > MIXBUFFERSIZE) return; - if (!buffer) return; - sid_fillbuffer(buffer, samples); - if (writehandle) - fwrite(buffer, samples * sizeof(Uint16), 1, writehandle); + if (numsids == 1) + { + if (!buffer) return; + sid_fillbuffer(buffer, samples); + if (writehandle) + { + fwrite(buffer, samples * sizeof(Uint16), 1, writehandle); + } - for (s = 0; s < samples; s++) - for (c = snd_channels; c; c--) - *dest++ = buffer[s]; + for (c = 0; c < samples; c++) + { + dest[c] = buffer[c]; + } + } + else if (numsids == 2) + { + sid_fillbuffer_stereo(lbuffer, rbuffer, samples); + if (writehandle) + { + for (c = 0; c < samples; c++) + { + fwrite(&lbuffer[c], sizeof(Sint16), 1, writehandle); + fwrite(&rbuffer[c], sizeof(Sint16), 1, writehandle); + } + } + if (monomode) + { + for (c = 0; c < samples; c++) + { + dest[c*2] = lbuffer[c] / 2 + rbuffer[c] / 2; + dest[c*2+1] = dest[c*2]; + } + } + else + { + for (c = 0; c < samples; c++) + { + dest[c*2] = lbuffer[c]; + dest[c*2+1] = rbuffer[c]; + } + } + } } diff --git a/src/gsound.h b/src/gsound.h index 5d1ead4..ce61cc4 100644 --- a/src/gsound.h +++ b/src/gsound.h @@ -13,8 +13,7 @@ #define MIXBUFFERSIZE 65536 int sound_init(unsigned mr, unsigned writer, unsigned m, unsigned ntsc, - unsigned multiplier, unsigned interpolate, - unsigned customclockrate, unsigned numsids, + unsigned multiplier, unsigned interpolate, unsigned customclockrate, unsigned exsid, float filterbias, unsigned combwaves); void sound_uninit(void); void sound_suspend(void); diff --git a/src/gt2reloc.c b/src/gt2reloc.c index fd627ae..2dc46af 100644 --- a/src/gt2reloc.c +++ b/src/gt2reloc.c @@ -61,6 +61,9 @@ unsigned interpolate = 0; unsigned residdelay = 0; float basepitch = 0.0f; +unsigned monomode = 0; +unsigned numsids = 1; + char configbuf[MAX_PATHNAME]; char loadedsongfilename[MAX_FILENAME]; char songfilename[MAX_FILENAME]; From 3f97c0aacc010faa9dda6f89a6fe590a673ff081 Mon Sep 17 00:00:00 2001 From: Leandro Nini Date: Sun, 5 Jul 2026 13:40:24 +0200 Subject: [PATCH 06/15] Apply changes from fork https://github.com/jansalleine/gt2fork/commit/a43f778eac8e1fcb8714c7415d3b930b69fed868 https://github.com/jansalleine/gt2fork/commit/37c6daea9ba5e95d6c6f7d5529f8fed520c37f09 https://github.com/jansalleine/gt2fork/commit/6aeba7de6992cfe9118d1e79a6f4358f79bd1f13 --- src/gcommon.h | 2 +- src/gdisplay.c | 8 +- src/goattrk2.c | 7 +- src/gorder.c | 25 ++- src/greloc.c | 4 +- src/gsong.c | 456 +++++++++++++++++++++++++++++++++++++++---------- src/gsong.h | 6 +- 7 files changed, 401 insertions(+), 107 deletions(-) diff --git a/src/gcommon.h b/src/gcommon.h index 1b46ff9..8b26566 100644 --- a/src/gcommon.h +++ b/src/gcommon.h @@ -26,7 +26,7 @@ #define MAX_FILT 64 #define MAX_STR 32 #define MAX_INSTR 64 -#define MAX_CHN 3 +#define MAX_CHN 6 #define MAX_CHN_MONO 3 #define MAX_PATT 208 #define MAX_TABLES 4 diff --git a/src/gdisplay.c b/src/gdisplay.c index c21a583..fa74420 100644 --- a/src/gdisplay.c +++ b/src/gdisplay.c @@ -62,9 +62,13 @@ void printstatus(void) { int c, d, color, color2; int cc = cursorcolortable[cursorflash]; - int visibleOrderlist = VISIBLEORDERLIST; + int visibleOrderlist = 14; int maxChns = MAX_CHN; - if (numsids == 1) maxChns = 3; + if (numsids == 1) + { + maxChns = 3; + visibleOrderlist = VISIBLEORDERLIST; + } menu = 0; if ((mouseb > MOUSEB_LEFT) && (mousey <= 1) && (!eamode)) menu = 1; diff --git a/src/goattrk2.c b/src/goattrk2.c index bf12fcf..03034a5 100644 --- a/src/goattrk2.c +++ b/src/goattrk2.c @@ -34,7 +34,7 @@ int followplay = 0; int hexnybble = -1; int stepsize = 4; int autoadvance = 0; -int defaultpatternlength = 64; +unsigned defaultpatternlength = 64; int cursorflash = 0; int cursorcolortable[] = {1,2,7,2}; int exitprogram = 0; @@ -170,6 +170,7 @@ int main(int argc, char **argv) { getparam(configfile, &mr); getparam(configfile, &sidmodel); + getparam(configfile, &numsids); getparam(configfile, &ntsc); getparam(configfile, (unsigned *)&fileformat); getparam(configfile, (unsigned *)&playeradr); @@ -466,6 +467,7 @@ int main(int argc, char **argv) "\n" ";reSIDfp mixing rate (in Hz)\n%d\n\n" ";reSIDfp model (0 = 6581, 1 = 8580)\n%d\n\n" + ";Number of SIDs (1, 2, default 1)\n%d\n\n" ";Timing mode (0 = PAL, 1 = NTSC)\n%d\n\n" ";Packer/relocator fileformat (0 = SID, 1 = PRG, 2 = BIN)\n%d\n\n" ";Packer/relocator player address\n$%04x\n\n" @@ -495,6 +497,7 @@ int main(int argc, char **argv) ";Use exSID (0 = off, 1 = on)\n%d\n\n", mr, sidmodel, + numsids, ntsc, fileformat, playeradr, @@ -1287,7 +1290,7 @@ void clear(void) if (cp == 1) { int selectdone = 0; - int olddpl = defaultpatternlength; + unsigned olddpl = defaultpatternlength; printtext(dpos.statusBottomX+20, dpos.statusBottomY, 15,"Pattern length:"); while (!selectdone) diff --git a/src/gorder.c b/src/gorder.c index 0668e5e..d77e773 100644 --- a/src/gorder.c +++ b/src/gorder.c @@ -29,6 +29,8 @@ void namecommands(void); void orderlistcommands(void) { int c, scrrep; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; if (hexnybble >= 0) { @@ -265,7 +267,7 @@ void orderlistcommands(void) } else { - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { if (eseditpos < songlen[esnum][c]) espos[c] = eseditpos; if (esend[c] < espos[c]) esend[c] = 0; @@ -286,14 +288,14 @@ void orderlistcommands(void) { if ((esend[eschn] != eseditpos) && (eseditpos > espos[eschn])) { - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { if (eseditpos < songlen[esnum][c]) esend[c] = eseditpos; } } else { - for (c = 0; c < MAX_CHN; c++) esend[c] = 0; + for (c = 0; c < maxChns; c++) esend[c] = 0; } } break; @@ -310,7 +312,7 @@ void orderlistcommands(void) { int c, d; - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { int start; @@ -378,7 +380,7 @@ void orderlistcommands(void) case KEY_UP: eschn--; - if (eschn < 0) eschn = MAX_CHN - 1; + if (eschn < 0) eschn = maxChns - 1; if ((eseditpos == songlen[esnum][eschn]) || (eseditpos > songlen[esnum][eschn]+1)) { eseditpos = songlen[esnum][eschn]+1; @@ -389,7 +391,7 @@ void orderlistcommands(void) case KEY_DOWN: eschn++; - if (eschn >= MAX_CHN) eschn = 0; + if (eschn >= maxChns) eschn = 0; if ((eseditpos == songlen[esnum][eschn]) || (eseditpos > songlen[esnum][eschn]+1)) { eseditpos = songlen[esnum][eschn]+1; @@ -589,8 +591,10 @@ void prevsong(void) void songchange(void) { int c; - - for (c = 0; c < MAX_CHN; c++) + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; + + for (c = 0; c < maxChns; c++) { espos[c] = 0; esend[c] = 0; @@ -611,7 +615,10 @@ void songchange(void) void updateviewtopos(void) { int c, d; - for (c = 0; c < MAX_CHN; c++) + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; + + for (c = 0; c < maxChns; c++) { for (d = espos[c]; d < songlen[esnum][c]; d++) { diff --git a/src/greloc.c b/src/greloc.c index 4f51a0c..f2b9c18 100644 --- a/src/greloc.c +++ b/src/greloc.c @@ -155,7 +155,7 @@ void relocator(void) unsigned char *instrwork = NULL; channels = 3; - //if (numsids == 2) channels = 6; + if (numsids == 2) channels = 6; fixedparams = 1; simplepulse = 1; firstnote = MAX_NOTES-1; @@ -206,7 +206,7 @@ void relocator(void) membuf_free(&dest); int maxChns = MAX_CHN; - //if (numsids == 1) maxChns = 3; + if (numsids == 1) maxChns = 3; // Process song-orderlists countpatternlengths(); diff --git a/src/gsong.c b/src/gsong.c index 126c8f9..ad21fd7 100644 --- a/src/gsong.c +++ b/src/gsong.c @@ -9,13 +9,15 @@ INSTR instr[MAX_INSTR]; unsigned char ltable[MAX_TABLES][MAX_TABLELEN]; unsigned char rtable[MAX_TABLES][MAX_TABLELEN]; -unsigned char songorder[MAX_SONGS][MAX_CHN][MAX_SONGLEN+2]; +unsigned char songorder[MAX_SONGS][MAX_CHN_MONO][MAX_SONGLEN+2]; +unsigned char songorder_stereo[MAX_SONGS][MAX_CHN][MAX_SONGLEN+2]; unsigned char pattern[MAX_PATT][MAX_PATTROWS*4+4]; char songname[MAX_STR]; char authorname[MAX_STR]; char copyrightname[MAX_STR]; int pattlen[MAX_PATT]; -int songlen[MAX_SONGS][MAX_CHN]; +int songlen[MAX_SONGS][MAX_CHN_MONO]; +int songlen_stereo[MAX_SONGS][MAX_CHN]; int highestusedpattern; int highestusedinstr; @@ -25,6 +27,9 @@ int savesong(void) char ident[] = {'G', 'T', 'S', '5'}; FILE *handle; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; + if (strlen(songfilename) < MAX_FILENAME-4) { int extfound = 0; @@ -61,13 +66,27 @@ int savesong(void) // Determine amount of songs to be saved c = MAX_SONGS - 1; - for (;;) + if (numsids == 1) { - if ((songlen[c][0])&& - (songlen[c][1])&& - (songlen[c][2])) break; - if (c == 0) break; - c--; + for (;;) + { + if ((songlen[c][0])&& + (songlen[c][1])&& + (songlen[c][2])) break; + if (c == 0) break; + c--; + } + } + else if (numsids == 2) + { + for (;;) + { + if ((songlen_stereo[c][0])&& + (songlen_stereo[c][1])&& + (songlen_stereo[c][2])) break; + if (c == 0) break; + c--; + } } amount = c + 1; @@ -75,13 +94,24 @@ int savesong(void) // Write songorderlists for (d = 0; d < amount; d++) { - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { - length = songlen[d][c]+1; - fwrite8(handle, length); - writebytes = length; - writebytes++; - fwrite(songorder[d][c], writebytes, 1, handle); + if (numsids == 1) + { + length = songlen[d][c]+1; + fwrite8(handle, length); + writebytes = length; + writebytes++; + fwrite(songorder[d][c], writebytes, 1, handle); + } + else if (numsids == 2) + { + length = songlen_stereo[d][c]+1; + fwrite8(handle, length); + writebytes = length; + writebytes++; + fwrite(songorder_stereo[d][c], writebytes, 1, handle); + } } } // Write amount of instruments @@ -180,6 +210,8 @@ void loadsong(void) int ok = 0; char ident[4]; FILE *handle; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; handle = fopen(songfilename, "rb"); @@ -204,12 +236,19 @@ void loadsong(void) amount = fread8(handle); for (d = 0; d < amount; d++) { - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { length = fread8(handle); loadsize = length; loadsize++; - fread(songorder[d][c], loadsize, 1, handle); + if (numsids == 1) + { + fread(songorder[d][c], loadsize, 1, handle); + } + else if (numsids == 2) + { + fread(songorder_stereo[d][c], loadsize, 1, handle); + } } } // Read instruments @@ -264,12 +303,19 @@ void loadsong(void) amount = fread8(handle); for (d = 0; d < amount; d++) { - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { length = fread8(handle); loadsize = length; loadsize++; - fread(songorder[d][c], loadsize, 1, handle); + if (numsids == 1) + { + fread(songorder[d][c], loadsize, 1, handle); + } + else if (numsids == 2) + { + fread(songorder_stereo[d][c], loadsize, 1, handle); + } } } // Read instruments @@ -356,12 +402,19 @@ void loadsong(void) amount = fread8(handle); for (d = 0; d < amount; d++) { - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { length = fread8(handle); loadsize = length; loadsize++; - fread(songorder[d][c], loadsize, 1, handle); + if (numsids == 1) + { + fread(songorder[d][c], loadsize, 1, handle); + } + else if (numsids == 2) + { + fread(songorder_stereo[d][c], loadsize, 1, handle); + } } } @@ -1230,6 +1283,8 @@ void loadinstrument(void) void clearsong(int cs, int cp, int ci, int ct, int cn) { int c; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; if (!(cs | cp | ci | ct | cn)) return; @@ -1241,7 +1296,7 @@ void clearsong(int cs, int cp, int ci, int ct, int cn) esmarkchn = -1; followplay = 0; - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { int d; chn[c].mute = 0; @@ -1255,18 +1310,41 @@ void clearsong(int cs, int cp, int ci, int ct, int cn) memset(loadedsongfilename, 0, sizeof loadedsongfilename); for (d = 0; d < MAX_SONGS; d++) { - memset(&songorder[d][c][0], 0, MAX_SONGLEN+2); - if (!d) + if (numsids == 1) { - songorder[d][c][0] = c; - songorder[d][c][1] = LOOPSONG; + memset(&songorder[d][c][0], 0, MAX_SONGLEN+2); + if (!d) + { + songorder[d][c][0] = c; + songorder[d][c][1] = LOOPSONG; + } + else + { + songorder[d][c][0] = LOOPSONG; + } } - else + else if (numsids == 2) { - songorder[d][c][0] = LOOPSONG; + memset(&songorder_stereo[d][c][0], 0, MAX_SONGLEN+2); + if (!d) + { + songorder_stereo[d][c][0] = c; + songorder_stereo[d][c][1] = LOOPSONG; + } + else + { + songorder_stereo[d][c][0] = LOOPSONG; + } } } - epnum[c] = songorder[0][c][0]; + if (numsids == 1) + { + epnum[c] = songorder[0][c][0]; + } + else if (numsids == 2) + { + epnum[c] = songorder_stereo[0][c][0]; + } espos[c] = 0; esend[c] = 0; } @@ -1320,6 +1398,8 @@ void clearsong(int cs, int cp, int ci, int ct, int cn) void countpatternlengths(void) { int c, d, e; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; highestusedpattern = 0; highestusedinstr = 0; @@ -1337,15 +1417,37 @@ void countpatternlengths(void) for (e = 0; e < MAX_SONGS; e++) { - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { for (d = 0; d < MAX_SONGLEN; d++) { - if (songorder[e][c][d] >= LOOPSONG) break; - if ((songorder[e][c][d] < REPEAT) && (songorder[e][c][d] > highestusedpattern)) - highestusedpattern = songorder[e][c][d]; + if (numsids == 1) + { + if (songorder[e][c][d] >= LOOPSONG) break; + if ((songorder[e][c][d] < REPEAT) && + (songorder[e][c][d] > highestusedpattern)) + { + highestusedpattern = songorder[e][c][d]; + } + } + else if (numsids == 2) + { + if (songorder_stereo[e][c][d] >= LOOPSONG) break; + if ((songorder_stereo[e][c][d] < REPEAT) && + (songorder_stereo[e][c][d] > highestusedpattern)) + { + highestusedpattern = songorder_stereo[e][c][d]; + } + } + } + if (numsids == 1) + { + songlen[e][c] = d; + } + else if (numsids == 2) + { + songlen_stereo[e][c] = d; } - songlen[e][c] = d; } } } @@ -1365,16 +1467,39 @@ void countthispattern(void) c = eschn; for (d = 0; d < MAX_SONGLEN; d++) { - if (songorder[e][c][d] >= LOOPSONG) break; - if (songorder[e][c][d] > highestusedpattern) - highestusedpattern = songorder[e][c][d]; + if (numsids == 1) + { + if (songorder[e][c][d] >= LOOPSONG) break; + if (songorder[e][c][d] > highestusedpattern) + { + highestusedpattern = songorder[e][c][d]; + } + } + else if (numsids == 2) + { + if (songorder_stereo[e][c][d] >= LOOPSONG) break; + if (songorder_stereo[e][c][d] > highestusedpattern) + { + highestusedpattern = songorder_stereo[e][c][d]; + } + } + } + if (numsids == 1) + { + songlen[e][c] = d; + } + else if (numsids == 2) + { + songlen_stereo[e][c] = d; } - songlen[e][c] = d; } int insertpattern(int p) { int c, d, e; + int tmp; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; findusedpatterns(); if (p >= MAX_PATT-2) return 0; @@ -1384,22 +1509,46 @@ int insertpattern(int p) for (c = 0; c < MAX_SONGS; c++) { - if ((songlen[c][0]) && - (songlen[c][1]) && - (songlen[c][2])) + if (((numsids==1)&&(songlen[c][0])&&(songlen[c][1])&&(songlen[c][2]))|| + ((numsids==2)&&(songlen_stereo[c][0])&& + (songlen_stereo[c][1])&&(songlen_stereo[c][2]))) { - for (d = 0; d < MAX_CHN; d++) + for (d = 0; d < maxChns; d++) { - for (e = 0; e < songlen[c][d]; e++) + if (numsids == 1) + { + tmp = songlen[c][d]; + } + else if (numsids == 2) { - if ((songorder[c][d][e] < REPEAT) && (songorder[c][d][e] > p) && (songorder[c][d][e] != MAX_PATT-1)) - songorder[c][d][e]++; + tmp = songlen_stereo[c][d]; + } + for (e = 0; e < tmp; e++) + { + if (numsids == 1) + { + if ((songorder[c][d][e] < REPEAT) && + (songorder[c][d][e] > p) && + (songorder[c][d][e] != MAX_PATT-1)) + { + songorder[c][d][e]++; + } + } + else if (numsids == 2) + { + if ((songorder_stereo[c][d][e] < REPEAT) && + (songorder_stereo[c][d][e] > p) && + (songorder_stereo[c][d][e] != MAX_PATT-1)) + { + songorder_stereo[c][d][e]++; + } + } } } } } - - for (c = 0; c < MAX_CHN; c++) + + for (c = 0; c < maxChns; c++) { if ((epnum[c] > p) && (epnum[c] != MAX_PATT-1)) epnum[c]++; } @@ -1410,6 +1559,9 @@ int insertpattern(int p) void deletepattern(int p) { int c, d, e; + int tmp; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; if (p == MAX_PATT-1) return; @@ -1419,22 +1571,44 @@ void deletepattern(int p) for (c = 0; c < MAX_SONGS; c++) { - if ((songlen[c][0]) && - (songlen[c][1]) && - (songlen[c][2])) + if (((numsids==1)&&(songlen[c][0])&&(songlen[c][1])&&(songlen[c][2]))|| + ((numsids==2)&&(songlen_stereo[c][0])&& + (songlen_stereo[c][1])&&(songlen_stereo[c][2]))) { - for (d = 0; d < MAX_CHN; d++) + for (d = 0; d < maxChns; d++) { - for (e = 0; e < songlen[c][d]; e++) + if (numsids == 1) + { + tmp = songlen[c][d]; + } + else if (numsids == 2) { - if ((songorder[c][d][e] < REPEAT) && (songorder[c][d][e] > p)) - songorder[c][d][e]--; + tmp = songlen_stereo[c][d]; + } + for (e = 0; e < tmp; e++) + { + if (numsids == 1) + { + if ((songorder[c][d][e] < REPEAT) && + (songorder[c][d][e] > p)) + { + songorder[c][d][e]--; + } + } + else if (numsids == 2) + { + if ((songorder_stereo[c][d][e] < REPEAT) && + (songorder_stereo[c][d][e] > p)) + { + songorder_stereo[c][d][e]--; + } + } } } } } - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { if (epnum[c] > p) epnum[c]--; } @@ -1452,21 +1626,44 @@ void clearpattern(int p) void findusedpatterns(void) { int c, d, e; + int tmp; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; countpatternlengths(); memset(pattused, 0, sizeof pattused); for (c = 0; c < MAX_SONGS; c++) { - if ((songlen[c][0]) && - (songlen[c][1]) && - (songlen[c][2])) + if (((numsids==1)&&(songlen[c][0])&&(songlen[c][1])&&(songlen[c][2]))|| + ((numsids==2)&&(songlen_stereo[c][0])&& + (songlen_stereo[c][1])&&(songlen_stereo[c][2]))) { - for (d = 0; d < MAX_CHN; d++) + for (d = 0; d < maxChns; d++) { - for (e = 0; e < songlen[c][d]; e++) + if (numsids == 1) + { + tmp = songlen[c][d]; + } + else if (numsids == 2) { - if (songorder[c][d][e] < REPEAT) - pattused[songorder[c][d][e]] = 1; + tmp = songlen_stereo[c][d]; + } + for (e = 0; e < tmp; e++) + { + if (numsids == 1) + { + if (songorder[c][d][e] < REPEAT) + { + pattused[songorder[c][d][e]] = 1; + } + } + else if (numsids == 2) + { + if (songorder_stereo[c][d][e] < REPEAT) + { + pattused[songorder_stereo[c][d][e]] = 1; + } + } } } } @@ -1476,39 +1673,84 @@ void findusedpatterns(void) void findduplicatepatterns(void) { int c, d; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; findusedpatterns(); - for (c = 0; c < MAX_PATT; c++) + if (numsids == 1) { - if (pattused[c]) + for (c = 0; c < MAX_PATT; c++) { - for (d = c+1; d < MAX_PATT; d++) + if (pattused[c]) { - if (pattlen[d] == pattlen[c]) + for (d = c+1; d < MAX_PATT; d++) { - if (!memcmp(pattern[c], pattern[d], pattlen[c]*4)) + if (pattlen[d] == pattlen[c]) { - int f, g, h; + if (!memcmp(pattern[c], pattern[d], pattlen[c]*4)) + { + int f, g, h; - for (f = 0; f < MAX_SONGS; f++) + for (f = 0; f < MAX_SONGS; f++) + { + if ((songlen[f][0]) && + (songlen[f][1]) && + (songlen[f][2])) + { + for (g = 0; g < maxChns; g++) + { + for (h = 0; h < songlen[f][g]; h++) + { + if (songorder[f][g][h] == d) + songorder[f][g][h] = c; + } + } + } + } + for (f = 0; f < maxChns; f++) + if (epnum[f] == d) epnum[f] = c; + } + } + } + } + } + } + else if (numsids == 2) + { + for (c = 0; c < MAX_PATT; c++) + { + if (pattused[c]) + { + for (d = c+1; d < MAX_PATT; d++) + { + if (pattlen[d] == pattlen[c]) + { + if (!memcmp(pattern[c], pattern[d], pattlen[c]*4)) { - if ((songlen[f][0]) && - (songlen[f][1]) && - (songlen[f][2])) + int f, g, h; + + for (f = 0; f < MAX_SONGS; f++) { - for (g = 0; g < MAX_CHN; g++) + if ((songlen_stereo[f][0]) && + (songlen_stereo[f][1]) && + (songlen_stereo[f][2])) { - for (h = 0; h < songlen[f][g]; h++) + for (g = 0; g < maxChns; g++) { - if (songorder[f][g][h] == d) - songorder[f][g][h] = c; + for (h = 0; h < songlen_stereo[f][g]; h++) + { + if (songorder_stereo[f][g][h] == d) + { + songorder_stereo[f][g][h] = c; + } + } } } } + for (f = 0; f < maxChns; f++) + if (epnum[f] == d) epnum[f] = c; } - for (f = 0; f < MAX_CHN; f++) - if (epnum[f] == d) epnum[f] = c; } } } @@ -1584,6 +1826,8 @@ void mergesong(void) int pattbase; int instrbase; int tablebase[MAX_TABLES]; + int maxChns = MAX_CHN; + if (numsids == 1) maxChns = 3; // Determine amount of patterns & instruments countpatternlengths(); @@ -1599,15 +1843,29 @@ void mergesong(void) // Determine amount of songs c = MAX_SONGS - 1; - for (;;) + if (numsids == 1) { - if ((songlen[c][0])&& - (songlen[c][1])&& - (songlen[c][2])) break; - if (c == 0) break; - c--; - } - + for (;;) + { + if ((songlen[c][0])&& + (songlen[c][1])&& + (songlen[c][2])) break; + if (c == 0) break; + c--; + } + } + else if (numsids == 2) + { + for (;;) + { + if ((songlen_stereo[c][0])&& + (songlen_stereo[c][1])&& + (songlen_stereo[c][2])) break; + if (c == 0) break; + c--; + } + } + pattbase = highestusedpattern + 1; instrbase = highestusedinstr; songbase = c + 1; @@ -1639,17 +1897,37 @@ void mergesong(void) goto ABORT; for (d = 0; d < amount; d++) { - for (c = 0; c < MAX_CHN; c++) + for (c = 0; c < maxChns; c++) { length = fread8(handle); loadsize = length; loadsize++; - fread(songorder[songbase + d][c], loadsize, 1, handle); + if (numsids == 1) + { + fread(songorder[songbase + d][c], loadsize, 1, handle); + } + else if (numsids == 2) + { + fread( + songorder_stereo[songbase + d][c], + loadsize, + 1, + handle + ); + } // Remap patterns for (e = 0; e < loadsize - 1; e++) { - if (songorder[songbase + d][c][e] < REPEAT) - songorder[songbase + d][c][e] += pattbase; + if (numsids == 1) + { + if (songorder[songbase + d][c][e] < REPEAT) + songorder[songbase + d][c][e] += pattbase; + } + else if (numsids == 2) + { + if (songorder_stereo[songbase + d][c][e] < REPEAT) + songorder_stereo[songbase + d][c][e] += pattbase; + } } } } diff --git a/src/gsong.h b/src/gsong.h index 0abbf2b..42bee12 100644 --- a/src/gsong.h +++ b/src/gsong.h @@ -5,13 +5,15 @@ extern INSTR instr[MAX_INSTR]; extern unsigned char ltable[MAX_TABLES][MAX_TABLELEN]; extern unsigned char rtable[MAX_TABLES][MAX_TABLELEN]; -extern unsigned char songorder[MAX_SONGS][MAX_CHN][MAX_SONGLEN+2]; +extern unsigned char songorder[MAX_SONGS][MAX_CHN_MONO][MAX_SONGLEN+2]; +extern unsigned char songorder_stereo[MAX_SONGS][MAX_CHN][MAX_SONGLEN+2]; extern unsigned char pattern[MAX_PATT][MAX_PATTROWS*4+4]; extern char songname[MAX_STR]; extern char authorname[MAX_STR]; extern char copyrightname[MAX_STR]; extern int pattlen[MAX_PATT]; -extern int songlen[MAX_SONGS][MAX_CHN]; +extern int songlen[MAX_SONGS][MAX_CHN_MONO]; +extern int songlen_stereo[MAX_SONGS][MAX_CHN]; extern int highestusedpattern; extern int highestusedinstr; #endif From f884f0a48d0fd5019b6783f182d00fbd2e63ecb7 Mon Sep 17 00:00:00 2001 From: Leandro Nini Date: Sun, 5 Jul 2026 15:19:04 +0200 Subject: [PATCH 07/15] Apply changes from fork https://github.com/jansalleine/gt2fork/commit/20f26f4b12b80bc75ba05621cfe27e5daeddb6a0 https://github.com/jansalleine/gt2fork/commit/be0f10efae7462248a9d7ee17b4f5a01fd23494a https://github.com/jansalleine/gt2fork/commit/adaa76750d78ac628d947c2ade7eeaa19e70e43a --- CMakeLists.txt | 43 -- src/altplayer_s.s | 1738 +++++++++++++++++++++++++++++++++++++++++++++ src/gdisplay.c | 48 +- src/goattrk2.c | 77 +- src/goattrk2.h | 1 + src/gorder.c | 555 ++++++++++++++- src/gorder.h | 5 + src/gplay.c | 1038 ++++++++++++++++++++++++++- src/gplay.h | 1 + src/greloc.c | 1618 +++++++++++++++++++++++++++++++++++++++-- src/greloc.h | 1 + src/gsong.c | 50 +- src/gsound.c | 9 +- src/gt2reloc.c | 447 ------------ src/loadtrk.seq | 3 +- src/player_s.s | 1731 ++++++++++++++++++++++++++++++++++++++++++++ 16 files changed, 6782 insertions(+), 583 deletions(-) create mode 100644 src/altplayer_s.s delete mode 100644 src/gt2reloc.c create mode 100644 src/player_s.s diff --git a/CMakeLists.txt b/CMakeLists.txt index 2def8c7..b2e9a48 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,43 +62,6 @@ if(MINGW) ) endif(MINGW) -# it would be nice not having to link things like residfp, however the source is -# not ready for that -set(GT2RELOC_SOURCES - ${CMAKE_BINARY_DIR}/src/goatdata.c - src/gt2reloc.c - src/gsong.c - src/gorder.c - src/gpattern.c - src/ginstr.c - src/gtable.c - src/gplay.c - src/gdisplay.c - src/gfile.c - src/ghelp.c - src/gsound.c - src/gconsole.c - src/gsid.cpp - src/asm/asmtab.c - src/asm/chnkpool.c - src/asm/expr.c - src/asm/lexyy.c - src/asm/log.c - src/asm/membuf.c - src/asm/membufio.c - src/asm/namedbuf.c - src/asm/parse.c - src/asm/pc.c - src/asm/vec.c - src/bme/bme_gfx.c - src/bme/bme_snd.c - src/bme/bme_win.c - src/bme/bme_mou.c - src/bme/bme_kbd.c - src/bme/bme_io.c - src/bme/bme_end.c - src/bme/bme.c) - set(MOD2SNG_SOURCES src/mod2sng.c src/bme/bme_end.c) @@ -141,14 +104,12 @@ add_custom_command( ) add_executable(loadtrk ${LOADTRK_SOURCES}) -add_executable(gt2reloc ${GT2RELOC_SOURCES}) add_executable(mod2sng ${MOD2SNG_SOURCES}) add_executable(ins2snd2 ${INS2SND2_SOURCES}) add_executable(sngspli2 ${SNGSPLI2_SOURCES}) add_custom_target(goatdata DEPENDS ${CMAKE_BINARY_DIR}/src/goatdata.c) add_dependencies(loadtrk goatdata) -add_dependencies(gt2reloc goatdata) target_include_directories(mod2sng PUBLIC SDL3::Headers) target_include_directories(ins2snd2 PUBLIC SDL3::Headers) @@ -162,10 +123,8 @@ OPTION(BUILD_STATIC "Static build" OFF) IF(BUILD_STATIC) set(CMAKE_EXE_LINKER_FLAGS "-static") target_link_libraries(loadtrk SDL3::SDL3-static) - target_link_libraries(gt2reloc SDL3::SDL3-static) ELSE() target_link_libraries(loadtrk SDL3::SDL3) - target_link_libraries(gt2reloc SDL3::SDL3) ENDIF() find_package(Jack) @@ -215,10 +174,8 @@ endif() pkg_check_modules(RESIDFP REQUIRED IMPORTED_TARGET libresidfp>=0.1) if(BUILD_STATIC) target_link_libraries(loadtrk PkgConfig::RESIDFP-static) - target_link_libraries(gt2reloc PkgConfig::RESIDFP-static) else() target_link_libraries(loadtrk PkgConfig::RESIDFP) - target_link_libraries(gt2reloc PkgConfig::RESIDFP) endif() ################################################################## diff --git a/src/altplayer_s.s b/src/altplayer_s.s new file mode 100644 index 0000000..2d7f4b6 --- /dev/null +++ b/src/altplayer_s.s @@ -0,0 +1,1738 @@ +;------------------------------------------------------------------------------- +; GoatTracker V2.74 stereo alternative SID write order playroutine +; +; NOTE: This playroutine source code does not fall under the GPL license! +; Use it, or song binaries created from it freely for any purpose, commercial +; or noncommercial. +; +; NOTE 2: This code is in the format of Magnus Lind's assembler from Exomizer. +; Does not directly compile on DASM etc. +;------------------------------------------------------------------------------- + + ;Defines will be inserted by the relocator here + +mt_temp1 = zpbase+0 +mt_temp2 = zpbase+1 + + ;Defines for the music data + ;Patterndata notes + +ENDPATT = $00 +INS = $00 +FX = $40 +FXONLY = $50 +NOTE = $60 +REST = $bd +KEYOFF = $be +KEYON = $bf +FIRSTPACKEDREST = $c0 +PACKEDREST = $00 + + ;Effects + +DONOTHING = $00 +PORTAUP = $01 +PORTADOWN = $02 +TONEPORTA = $03 +VIBRATO = $04 +SETAD = $05 +SETSR = $06 +SETWAVE = $07 +SETWAVEPTR = $08 +SETPULSEPTR = $09 +SETFILTPTR = $0a +SETFILTCTRL = $0b +SETFILTCUTOFF = $0c +SETMASTERVOL = $0d +SETFUNKTEMPO = $0e +SETTEMPO = $0f + + ;Orderlist commands + +REPEAT = $d0 +TRANSDOWN = $e0 +TRANS = $f0 +TRANSUP = $f0 +LOOPSONG = $ff + + ;Wave,pulse,filttable comands + +LOOPWAVE = $ff +LOOPPULSE = $ff +LOOPFILT = $ff +SETPULSE = $80 +SETFILTER = $80 +SETCUTOFF = $00 + + .ORG (base) + + ;Jump table + + jmp mt_init + jmp mt_play + .IF (SOUNDSUPPORT != 0) + jmp mt_playsfx + .ENDIF + .IF (VOLSUPPORT != 0) + jmp mt_setmastervol + .ENDIF + + ;Author info + + .IF (NOAUTHORINFO == 0) + +authorinfopos = base + $20 +checkpos1: + .IF ((authorinfopos - checkpos1) > 15) +mt_tick0jumptbl: + .BYTE (mt_tick0_0 % 256) + .BYTE (mt_tick0_12 % 256) + .BYTE (mt_tick0_12 % 256) + .BYTE (mt_tick0_34 % 256) + .BYTE (mt_tick0_34 % 256) + .BYTE (mt_tick0_5 % 256) + .BYTE (mt_tick0_6 % 256) + .BYTE (mt_tick0_7 % 256) + .BYTE (mt_tick0_8 % 256) + .BYTE (mt_tick0_9 % 256) + .BYTE (mt_tick0_a % 256) + .BYTE (mt_tick0_b % 256) + .BYTE (mt_tick0_c % 256) + .BYTE (mt_tick0_d % 256) + .BYTE (mt_tick0_e % 256) + .BYTE (mt_tick0_f % 256) + .ENDIF + +checkpos2: + .IF ((authorinfopos - checkpos2) > 4) +mt_effectjumptbl: + .BYTE (mt_effect_0 % 256) + .BYTE (mt_effect_12 % 256) + .BYTE (mt_effect_12 % 256) + .BYTE (mt_effect_3 % 256) + .BYTE (mt_effect_4 % 256) + .ENDIF + +checkpos3: + .IF ((authorinfopos - checkpos3) > 1) +mt_funktempotbl: + .BYTE (8,5) + .ENDIF + + ;This is pretty stupid way of filling left-out space, but .ORG + ;seemed to bug + +checkpos4: + .IF ((authorinfopos - checkpos4) > 0) .BYTE (0) .ENDIF +checkpos5: + .IF ((authorinfopos - checkpos5) > 0) .BYTE (0) .ENDIF +checkpos6: + .IF ((authorinfopos - checkpos6) > 0) .BYTE (0) .ENDIF + +mt_author: + + .BYTE (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) + .BYTE (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) + .ENDIF + + ;0 Instrument vibrato + +mt_tick0_0: + .IF (NOEFFECTS == 0) + .IF (NOINSTRVIB == 0) + lda mt_insvibparam-1,y + jmp mt_tick0_34 + .ELSE + .IF (NOVIB == 0) + jmp mt_tick0_34 + .ENDIF + .ENDIF + .ENDIF + + ;1,2 Portamentos + + +mt_tick0_12: + .IF (NOVIB == 0) + tay + lda #$00 + sta mt_chnvibtime,x + tya + .ENDIF + + ;3,4 Toneportamento, Vibrato + +mt_tick0_34: + .IF (NOEFFECTS == 0) + .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0)) + sta mt_chnparam,x + lda mt_chnnewfx,x + sta mt_chnfx,x + .ENDIF + rts + .ENDIF + + ;5 Set AD + +mt_tick0_5: + .IF (NOSETAD == 0) + sta mt_chnad,x + rts + .ENDIF + + ;6 Set Sustain/Release + +mt_tick0_6: + .IF (NOSETSR == 0) + sta mt_chnsr,x + rts + .ENDIF + + ;7 Set waveform + +mt_tick0_7: + .IF (NOSETWAVE == 0) + sta mt_chnwave,x + rts + .ENDIF + + ;8 Set wavepointer + +mt_tick0_8: + .IF (NOSETWAVEPTR == 0) + sta mt_chnwaveptr,x + .IF (NOWAVEDELAY == 0) + lda #$00 ;Make sure possible delayed + sta mt_chnwavetime,x ;waveform execution goes + .ENDIF ;correctly + rts + .ENDIF + + ;9 Set pulsepointer + +mt_tick0_9: + .IF (NOSETPULSEPTR == 0) + sta mt_chnpulseptr,x + lda #$00 ;Reset pulse step duration + sta mt_chnpulsetime,x + rts + .ENDIF + + ;a Set filtpointer + +mt_tick0_a: + .IF (NOSETFILTPTR == 0) + cpx #21 + bcs mt_tick0_a_sid2 + .IF (NOFILTERMOD == 0) + ldy #$00 + sty mt_filttime+1 + .ENDIF +mt_tick0_a_step: + sta mt_filtstep+1 + rts + .ENDIF + +mt_tick0_a_sid2: + .IF (NOSETFILTPTR == 0) + .IF (NOFILTERMOD == 0) + ldy #$00 + sty mt_filttime_sid2+1 + .ENDIF +mt_tick0_a_step_sid2: + sta mt_filtstep_sid2+1 + rts + .ENDIF + + ;b Set filtcontrol (channels & resonance) + +mt_tick0_b: + .IF (NOSETFILTCTRL == 0) + cpx #21 + bcs mt_tick0_b_sid2 + sta mt_filtctrl+1 + cmp #$00 + .IF (NOSETFILTPTR == 0) + beq mt_tick0_a_step ;If 0, stop also step-programming + .ELSE + bne mt_tick0_b_noset + sta mt_filtstep+1 +mt_tick0_b_noset: + .ENDIF + rts + .ENDIF + +mt_tick0_b_sid2: + .IF (NOSETFILTCTRL == 0) + sta mt_filtctrl_sid2+1 + cmp #$00 + .IF (NOSETFILTPTR == 0) + beq mt_tick0_a_step_sid2 ;If 0, stop also step-programming + .ELSE + bne mt_tick0_b_noset_sid2 + sta mt_filtstep_sid2+1 +mt_tick0_b_noset_sid2: + .ENDIF + rts + .ENDIF + + + ;c Set cutoff + +mt_tick0_c: + .IF (NOSETFILTCUTOFF == 0) + cpx #21 + bcs mt_tick0_c_sid2 + sta mt_filtcutoff+1 + rts + .ENDIF + +mt_tick0_c_sid2: + .IF (NOSETFILTCUTOFF == 0) + sta mt_filtcutoff_sid2+1 + rts + .ENDIF + + ;d Set mastervolume / timing mark + +mt_tick0_d: + .IF (NOSETMASTERVOL == 0) + .IF (NOAUTHORINFO == 0) + cmp #$10 + bcs mt_tick0_d_timing + .ENDIF +mt_setmastervol: + sta mt_masterfader+1 + rts + .IF (NOAUTHORINFO == 0) +mt_tick0_d_timing: + sta mt_author+31 + rts + .ENDIF + .ENDIF + + ;e Funktempo + +mt_tick0_e: + .IF (NOFUNKTEMPO == 0) + tay + lda mt_speedlefttbl-1,y + sta mt_funktempotbl + lda mt_speedrighttbl-1,y + sta mt_funktempotbl+1 + lda #$00 + .IF (NOCHANNELTEMPO == 0) + beq mt_tick0_f_setglobaltempo + .ENDIF + .ENDIF + + ;f Set Tempo + +mt_tick0_f: + .IF ((NOCHANNELTEMPO == 0) && (NOGLOBALTEMPO == 0)) + bmi mt_tick0_f_setchantempo ;Channel or global tempo? + .ENDIF +mt_tick0_f_setglobaltempo: + .IF (NOGLOBALTEMPO == 0) + sta mt_chntempo + sta mt_chntempo+7 + sta mt_chntempo+14 + sta mt_chntempo+21 + sta mt_chntempo+28 + sta mt_chntempo+35 + rts + .ENDIF +mt_tick0_f_setchantempo: + .IF (NOCHANNELTEMPO == 0) + and #$7f + sta mt_chntempo,x + rts + .ENDIF + + ;Continuous effect code + + ;0 Instrument vibrato + + .IF (NOINSTRVIB == 0) +mt_effect_0_delay: + dec mt_chnvibdelay,x +mt_effect_0_donothing: + jmp mt_done +mt_effect_0: beq mt_effect_0_donothing ;Speed 0 = no vibrato at all + lda mt_chnvibdelay,x + bne mt_effect_0_delay + .ELSE +mt_effect_0: +mt_effect_0_donothing: + jmp mt_done + .ENDIF + + ;4 Vibrato + +mt_effect_4: + .IF (NOVIB == 0) + .IF (NOCALCULATEDSPEED == 0) + lda mt_speedlefttbl-1,y + .IF (NONORMALSPEED == 0) + bmi mt_effect_4_nohibyteclear + ldy #$00 ;Clear speed highbyte + sty 1) + asl + sta mt_init+6 + asl + adc #$00 + .ENDIF + sta mt_initsongnum+1 + rts + + ;Play soundeffect -routine + + .IF (SOUNDSUPPORT != 0) + ;Sound FX init routine + +mt_playsfx: sta mt_playsfxlo+1 + sty mt_playsfxhi+1 + lda mt_chnsfx,x ;Need a priority check? + beq mt_playsfxok + tya ;Check address highbyte + cmp mt_chnsfxhi,x + bcc mt_playsfxskip ;Lower than current -> skip + bne mt_playsfxok ;Higher than current -> OK + lda mt_playsfxlo+1 ;Check address lowbyte + cmp mt_chnsfxlo,x + bcc mt_playsfxskip ;Lower than current -> skip +mt_playsfxok: lda #$01 + sta mt_chnsfx,x +mt_playsfxlo: lda #$00 + sta mt_chnsfxlo,x +mt_playsfxhi: lda #$00 + sta mt_chnsfxhi,x +mt_playsfxskip: rts + .ENDIF + + ;Set mastervolume -routine + + .IF ((VOLSUPPORT != 0) && (NOSETMASTERVOL != 0)) +mt_setmastervol: + sta mt_masterfader+1 + rts + .ENDIF + + ;Playroutine + +mt_play: ldx #$00 ;Channel index + + ;Song initialization + +mt_initsongnum: + ldy #$00 + bmi mt_filtstep + txa + ldx #NUMCHANNELS * 14 - 1 +mt_resetloop: + sta mt_chnsongptr,x ;Reset sequencer + voice + dex ;variables on all channels + bpl mt_resetloop + sta SIDBASE+$15 ;Reset filter cutoff lowbyte + sta SID2BASE+$15 + sta mt_filtctrl+1 ;Switch filter off & reset + sta mt_filtctrl_sid2+1 + .IF (NOFILTER == 0) + sta mt_filtstep+1 ;step-programming + sta mt_filtstep_sid2+1 + .ENDIF + stx mt_initsongnum+1 ;Reset initflag + tax + jsr mt_initchn + ldx #$07 + jsr mt_initchn + ldx #$0e + jsr mt_initchn + ldx #$15 + jsr mt_initchn + ldx #$1c + jsr mt_initchn + ldx #$23 +mt_initchn: + .IF (NUMSONGS > 1) + tya + iny + sta mt_chnsongnum,x ;Store index to songtable + .ENDIF +mt_defaulttempo: + lda #DEFAULTTEMPO ;Set default tempo + sta mt_chntempo,x + lda #$01 + sta mt_chncounter,x ;Reset counter + sta mt_chninstr,x ;Reset instrument + jmp mt_loadregswave + + ;Filter execution + +mt_filtstep: + .IF (NOFILTER == 0) + ldy #$00 ;See if filter stopped + beq mt_filtdone + .IF (NOFILTERMOD == 0) +mt_filttime: + lda #$00 ;See if time left for mod. + bne mt_filtmod ;step + .ENDIF +mt_newfiltstep: + lda mt_filttimetbl-1,y ;$80-> = set filt parameters + beq mt_setcutoff ;$00 = set cutoff + .IF (NOFILTERMOD == 0) + bpl mt_newfiltmod + .ENDIF +mt_setfilt: + asl ;Set passband + sta mt_filttype+1 + lda mt_filtspdtbl-1,y ;Set resonance/channel + sta mt_filtctrl+1 + lda mt_filttimetbl,y ;Check for cutoff setting + bne mt_nextfiltstep2 ;following immediately +mt_setcutoff2: + iny +mt_setcutoff: + lda mt_filtspdtbl-1,y ;Take cutoff value + sta mt_filtcutoff+1 + .IF (NOFILTERMOD == 0) + jmp mt_nextfiltstep +mt_newfiltmod: + sta mt_filttime+1 ;$01-$7f = new modulation step +mt_filtmod: + lda mt_filtspdtbl-1,y ;Take filt speed + clc + adc mt_filtcutoff+1 + sta mt_filtcutoff+1 + dec mt_filttime+1 + bne mt_storecutoff + .ENDIF +mt_nextfiltstep: + lda mt_filttimetbl,y ;Jump in filttable? +mt_nextfiltstep2: + cmp #LOOPFILT + iny + tya + bcc mt_nofiltjump + lda mt_filtspdtbl-1,y ;Take jump point +mt_nofiltjump: + sta mt_filtstep+1 +mt_filtdone: +mt_filtcutoff: + lda #$00 +mt_storecutoff: + sta SIDBASE+$16 + .ENDIF +mt_filtctrl: + lda #$00 + sta SIDBASE+$17 +mt_filttype: + lda #$00 +mt_masterfader: + ora #$0f ;Master volume fader + sta SIDBASE+$18 + + ;Second filter execution + +mt_filtstep_sid2: + .IF (NOFILTER == 0) + ldy #$00 ;See if filter stopped + beq mt_filtdone_sid2 + .IF (NOFILTERMOD == 0) +mt_filttime_sid2: + lda #$00 ;See if time left for mod. + bne mt_filtmod_sid2 ;step + .ENDIF +mt_newfiltstep_sid2: + lda mt_filttimetbl-1,y ;$80-> = set filt parameters + beq mt_setcutoff_sid2 ;$00 = set cutoff + .IF (NOFILTERMOD == 0) + bpl mt_newfiltmod_sid2 + .ENDIF +mt_setfilt_sid2: + asl ;Set passband + sta mt_filttype_sid2+1 + lda mt_filtspdtbl-1,y ;Set resonance/channel + sta mt_filtctrl_sid2+1 + lda mt_filttimetbl,y ;Check for cutoff setting + bne mt_nextfiltstep2_sid2 ;following immediately +mt_setcutoff2_sid2: + iny +mt_setcutoff_sid2: + lda mt_filtspdtbl-1,y ;Take cutoff value + sta mt_filtcutoff_sid2+1 + .IF (NOFILTERMOD == 0) + jmp mt_nextfiltstep_sid2 +mt_newfiltmod_sid2: + sta mt_filttime_sid2+1 ;$01-$7f = new modulation step +mt_filtmod_sid2: + lda mt_filtspdtbl-1,y ;Take filt speed + clc + adc mt_filtcutoff_sid2+1 + sta mt_filtcutoff_sid2+1 + dec mt_filttime_sid2+1 + bne mt_storecutoff_sid2 + .ENDIF +mt_nextfiltstep_sid2: + lda mt_filttimetbl,y ;Jump in filttable? +mt_nextfiltstep2_sid2: + cmp #LOOPFILT + iny + tya + bcc mt_nofiltjump_sid2 + lda mt_filtspdtbl-1,y ;Take jump point +mt_nofiltjump_sid2: + sta mt_filtstep_sid2+1 +mt_filtdone_sid2: +mt_filtcutoff_sid2: + lda #$00 +mt_storecutoff_sid2: + sta SID2BASE+$16 + .ENDIF +mt_filtctrl_sid2: + lda #$00 + sta SID2BASE+$17 +mt_filttype_sid2: + lda #$00 + ora mt_masterfader+1 ;Master volume fader + sta SID2BASE+$18 + + ;Channel execution + + jsr mt_execchn + ldx #$07 + jsr mt_execchn + ldx #$0e + jsr mt_execchn + ldx #$15 + jsr mt_execchn + ldx #$1c + jsr mt_execchn + ldx #$23 + +mt_execchn: + dec mt_chncounter,x ;See if tick 0 + beq mt_tick0 + + ;Ticks 1-n + +mt_notick0: + bpl mt_effects + lda mt_chntempo,x ;Reload tempo if negative + + .IF (NOFUNKTEMPO == 0) + cmp #$02 + bcs mt_nofunktempo ;Funktempo: bounce between + tay ;funktable indexes 0,1 + eor #$01 + sta mt_chntempo,x + lda mt_funktempotbl,y + sbc #$00 + .ENDIF + +mt_nofunktempo: + sta mt_chncounter,x +mt_effects: + jmp mt_waveexec + + ;Sequencer repeat + +mt_repeat: + .IF (NOREPEAT == 0) + sbc #REPEAT + inc mt_chnrepeat,x + cmp mt_chnrepeat,x + bne mt_nonewpatt +mt_repeatdone: + lda #$00 + sta mt_chnrepeat,x + beq mt_repeatdone2 + .ENDIF + + ;Tick 0 + +mt_tick0: + .IF (NOEFFECTS == 0) + ldy mt_chnnewfx,y ;Setup tick 0 FX jumps + lda mt_tick0jumptbl,y + sta mt_tick0jump1+1 + sta mt_tick0jump2+1 + .ENDIF + + ;Sequencer advance + +mt_checknewpatt: + lda mt_chnpattptr,x ;Fetch next pattern? + bne mt_nonewpatt +mt_sequencer: + ldy mt_chnsongnum,y + lda mt_songtbllo,y ;Get address of sequence + sta 0) || (NOFIRSTWAVECMD == 0)) + lda #$ff +mt_skipwave2: + sta mt_chngate,x ;Reset gateflag + .ELSE + inc mt_chngate,x + .ENDIF +mt_skipwave: + + .IF (NOPULSE == 0) + lda mt_inspulseptr-1,y ;Load pulseptr (if nonzero) + beq mt_skippulse + sta mt_chnpulseptr,x + .IF (NOPULSEMOD == 0) + lda #$00 ;Reset pulse step duration + sta mt_chnpulsetime,x + .ENDIF + .ENDIF +mt_skippulse: + .IF (NOFILTER == 0) + cpx #21 + lda mt_insfiltptr-1,y ;Load filtptr (if nonzero) + beq mt_skipfilt + bcs mt_loadfilt_sid2 +mt_loadfilt: + sta mt_filtstep+1 + .IF (NOFILTERMOD == 0) + lda #$00 + sta mt_filttime+1 + .ENDIF + bcc mt_skipfilt +mt_loadfilt_sid2: + sta mt_filtstep_sid2+1 + .IF (NOFILTERMOD == 0) + lda #$00 + sta mt_filttime_sid2+1 + .ENDIF + .ENDIF +mt_skipfilt: + + lda mt_inswaveptr-1,y ;Load waveptr + sta mt_chnwaveptr,x + + lda mt_insad-1,y ;Load Attack/Decay + sta mt_chnad,x + lda mt_inssr-1,y ;Load Sustain/Release + sta mt_chnsr,x + + .IF (NOEFFECTS == 0) + lda mt_chnnewparam,x ;Execute tick 0 FX after +mt_tick0jump1: + jsr mt_tick0_0 ;newnote init + .ENDIF + jmp mt_loadregs + + .IF (NOWAVECMD == 0) +mt_wavecmd: + jmp mt_execwavecmd + .ENDIF + + ;Tick 0 effect execution + +mt_nonewnoteinit: + .IF (NOEFFECTS == 0) + lda mt_chnnewparam,x ;No new note init: exec tick 0 +mt_tick0jump2: + jsr mt_tick0_0 ;FX, and wavetable afterwards + .ENDIF + + ;Wavetable execution + +mt_waveexec: + ldy mt_chnwaveptr,y + beq mt_wavedone + lda mt_wavetbl-1,y + .IF (NOWAVEDELAY == 0) + cmp #$10 ;0-15 used as delay + bcs mt_nowavedelay ;+ no wave change + cmp mt_chnwavetime,x + beq mt_nowavechange + inc mt_chnwavetime,x + bne mt_wavedone +mt_nowavedelay: + sbc #$10 + .ELSE + beq mt_nowavechange + .ENDIF + .IF (NOWAVECMD == 0) + cmp #$e0 + bcs mt_nowavechange + .ENDIF + sta mt_chnwave,x +mt_nowavechange: + lda mt_wavetbl,y + cmp #LOOPWAVE ;Check for wavetable jump + iny + tya + bcc mt_nowavejump + .IF (NOWAVECMD != 0) + clc + .ENDIF + lda mt_notetbl-1,y +mt_nowavejump: + sta mt_chnwaveptr,x + .IF (NOWAVEDELAY == 0) + lda #$00 + sta mt_chnwavetime,x + .ENDIF + + .IF (NOWAVECMD == 0) + lda mt_wavetbl-2,y + cmp #$e0 + bcs mt_wavecmd + .ENDIF + + lda mt_notetbl-2,y + + .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0)) + bne mt_wavefreq ;No frequency-change? + + ;No frequency-change / continuous effect execution + +mt_wavedone: + .IF (REALTIMEOPTIMIZATION != 0) + lda mt_chncounter,x ;No continuous effects on tick0 + .IF (PULSEOPTIMIZATION != 0) + beq mt_gatetimer + .ELSE + beq mt_done + .ENDIF + .ENDIF + .IF (NOEFFECTS == 0) + ldy mt_chnfx,y + .IF (NOWAVECMD == 0) + .IF (.DEFINED(mt_effectnum)) + sty mt_effectnum+1 + .ENDIF + .ENDIF + lda mt_effectjumptbl,y + sta mt_effectjump+1 + ldy mt_chnparam,y + .ELSE + ldy mt_chninstr,y + lda mt_insvibparam-1,y + tay + .ENDIF +mt_setspeedparam: + .IF (NOCALCULATEDSPEED != 0) + lda mt_speedrighttbl-1,y + sta 0) && (NUMNOHRINSTR > 0)) || (NUMLEGATOINSTR > 0)) + lda mt_chninstr,x + cmp #FIRSTNOHRINSTR ;Instrument order: + .IF (NUMLEGATOINSTR > 0) + bcs mt_nohr_legato ;With HR - no HR - legato + .ELSE + bcs mt_skiphr + .ENDIF + .ENDIF + .IF (NUMHRINSTR > 0) + lda #ADPARAM ;Hard restart + sta mt_chnad,x + lda #SRPARAM + sta mt_chnsr,x + .ENDIF +mt_skiphr: + lda #$fe +mt_setgate: + sta mt_chngate,x + + ;Check for end of pattern + +mt_rest: + iny + lda (mt_temp1),y + beq mt_endpatt + tya +mt_endpatt: + sta mt_chnpattptr,x + + ;Load voice registers + +mt_loadregs: + .IF (SOUNDSUPPORT != 0) + ldy mt_chnsfx,y + bne mt_sfxexec + .ENDIF + +mt_loadregswave: + cpx #21 + bcs mt_loadregswave_sid2 + +mt_loadregswave_sid1: + lda mt_chnwave,x + and mt_chngate,x + sta SIDBASE+$04,x + lda mt_chnfreqlo,x + sta SIDBASE+$00,x + lda mt_chnfreqhi,x + sta SIDBASE+$01,x + lda mt_chnpulselo,x + .IF (SIMPLEPULSE == 0) + sta SIDBASE+$02,x + lda mt_chnpulsehi,x + sta SIDBASE+$03,x + .ELSE + sta SIDBASE+$02,x + sta SIDBASE+$03,x + .ENDIF + .IF (SOUNDSUPPORT != 0) + lda mt_chnsfx,x + bne mt_loadskipadsr + .ENDIF + lda mt_chnad,x + sta SIDBASE+$05,x + lda mt_chnsr,x + sta SIDBASE+$06,x +mt_loadskipadsr: + rts + + + .IF (NUMLEGATOINSTR > 0) +mt_nohr_legato: + cmp #FIRSTLEGATOINSTR + bcc mt_skiphr + bcs mt_rest + .ENDIF + +mt_loadregswave_sid2: + lda mt_chnwave,x + and mt_chngate,x + sta SID2BASE-21+$04,x + lda mt_chnfreqlo,x + sta SID2BASE-21+$00,x + lda mt_chnfreqhi,x + sta SID2BASE-21+$01,x + lda mt_chnpulselo,x + .IF (SIMPLEPULSE == 0) + sta SID2BASE-21+$02,x + lda mt_chnpulsehi,x + sta SID2BASE-21+$03,x + .ELSE + sta SID2BASE-21+$02,x + sta SID2BASE-21+$03,x + .ENDIF + .IF (SOUNDSUPPORT != 0) + lda mt_chnsfx,x + bne mt_loadskipadsr_sid2 + .ENDIF + lda mt_chnad,x + sta SID2BASE-21+$05,x + lda mt_chnsr,x + sta SID2BASE-21+$06,x +mt_loadskipadsr_sid2: + rts + + ;Sound FX code + + .IF (SOUNDSUPPORT != 0) + +mt_sfxexec: lda mt_chnsfxlo,x + sta songlen[esnum][c]) newpos = songlen[esnum][c]; + if (newpos > currentSonglen) newpos = currentSonglen; if ((c == eschn) && (chn[c].advance)) { @@ -281,6 +293,18 @@ void printstatus(void) for (d = 0; d < visibleOrderlist; d++) { int p = esview+d; + unsigned char currentSongorder = 0; + int currentSonglen = 0; + if (numsids == 1) + { + currentSongorder = songorder[esnum][c][p]; + currentSonglen = songlen[esnum][c]; + } + else if (numsids == 2) + { + currentSongorder = songorder_stereo[esnum][c][p]; + currentSonglen = songlen_stereo[esnum][c]; + } color = colors.CNORMAL; if (isplaying()) { @@ -292,42 +316,42 @@ void printstatus(void) if (p == espos[c]) color = colors.CEDIT; if ((esend[c]) && (p == esend[c])) color = colors.CEDIT; - if ((p < 0) || (p > (songlen[esnum][c]+1)) || (p > MAX_SONGLEN+1)) + if ((p < 0) || (p > (currentSonglen+1)) || (p > MAX_SONGLEN+1)) { sprintf(textbuffer, " "); } else { - if (songorder[esnum][c][p] < LOOPSONG) + if (currentSongorder < LOOPSONG) { - if ((songorder[esnum][c][p] < REPEAT) || (p >= songlen[esnum][c])) + if ((currentSongorder < REPEAT) || (p >= currentSonglen)) { - sprintf(textbuffer, "%02X ", songorder[esnum][c][p]); - if ((p >= songlen[esnum][c]) && (color == colors.CNORMAL)) color = colors.CCOMMAND; + sprintf(textbuffer, "%02X ", currentSongorder); + if ((p >= currentSonglen) && (color == colors.CNORMAL)) color = colors.CCOMMAND; } else { - if (songorder[esnum][c][p] >= TRANSUP) + if (currentSongorder >= TRANSUP) { - sprintf(textbuffer, "+%01X ", songorder[esnum][c][p]&0xf); + sprintf(textbuffer, "+%01X ", currentSongorder&0xf); if (color == colors.CNORMAL) color = colors.CCOMMAND; } else { - if (songorder[esnum][c][p] >= TRANSDOWN) + if (currentSongorder >= TRANSDOWN) { - sprintf(textbuffer, "-%01X ", 16-(songorder[esnum][c][p] & 0x0f)); + sprintf(textbuffer, "-%01X ", 16-(currentSongorder & 0x0f)); if (color == colors.CNORMAL) color = colors.CCOMMAND; } else { - sprintf(textbuffer, "R%01X ", (songorder[esnum][c][p]+1) & 0x0f); + sprintf(textbuffer, "R%01X ", (currentSongorder+1) & 0x0f); if (color == colors.CNORMAL) color = colors.CCOMMAND; } } } } - if (songorder[esnum][c][p] == LOOPSONG) + if (currentSongorder == LOOPSONG) { sprintf(textbuffer, "RST"); if (color == colors.CNORMAL) color = colors.CCOMMAND; diff --git a/src/goattrk2.c b/src/goattrk2.c index 03034a5..23b13e5 100644 --- a/src/goattrk2.c +++ b/src/goattrk2.c @@ -52,6 +52,7 @@ unsigned adparam = 0x0f00; unsigned ntsc = 0; unsigned patterndispmode = 2; unsigned sidaddress = 0xd400; +unsigned sid2address = 0xd500; unsigned finevibrato = 1; unsigned optimizepulse = 1; unsigned optimizerealtime = 1; @@ -184,6 +185,7 @@ int main(int argc, char **argv) getparam(configfile, &interpolate); getparam(configfile, &patterndispmode); getparam(configfile, &sidaddress); + getparam(configfile, &sid2address); getparam(configfile, &finevibrato); getparam(configfile, &optimizepulse); getparam(configfile, &optimizerealtime); @@ -372,6 +374,7 @@ int main(int argc, char **argv) zeropageadr &= 0xff; playeradr &= 0xff00; sidaddress &= 0xffff; + sid2address &= 0xffff; if (!stepsize) stepsize = 4; if (multiplier > 16) multiplier = 16; if (keypreset > 2) keypreset = 0; @@ -481,6 +484,7 @@ int main(int argc, char **argv) ";reSIDfp resampling mode (0 = interpolation, 1 = resampling)\n%d\n\n" ";Pattern display mode (0 = decimal, 1 = hex, 2 = decimal w/dots, 3 = hex w/dots)\n%d\n\n" ";SID baseaddress\n$%04x\n\n" + ";2nd SID baseaddress\n$%04x\n\n" ";Finevibrato mode (0 = off, 1 = on)\n%d\n\n" ";Pulseskipping (0 = off, 1 = on)\n%d\n\n" ";Realtime effect skipping (0 = off, 1 = on)\n%d\n\n" @@ -511,6 +515,7 @@ int main(int argc, char **argv) interpolate, patterndispmode, sidaddress, + sid2address, finevibrato, optimizepulse, optimizerealtime, @@ -615,7 +620,14 @@ void docommand(void) switch(editmode) { case EDIT_ORDERLIST: - orderlistcommands(); + if (numsids == 1) + { + orderlistcommands(); + } + else if (numsids == 2) + { + orderlistcommands_stereo(); + } break; case EDIT_INSTRUMENT: @@ -645,6 +657,16 @@ void mousecommands(void) int maxChns = MAX_CHN; if (numsids == 1) maxChns = 3; + int currentSonglen = 0; + if (numsids == 1) + { + currentSonglen = songlen[esnum][eschn]; + } + else if (numsids == 2) + { + currentSonglen = songlen_stereo[esnum][eschn]; + } + if (!mouseb) return; // Pattern editpos & pattern number selection @@ -734,20 +756,20 @@ void mousecommands(void) newpos = 0; newcolumn = 0; } - if (newpos == songlen[esnum][eschn]) + if (newpos == currentSonglen) { newpos++; newcolumn = 0; } - if (newpos > songlen[esnum][eschn]+1) + if (newpos > currentSonglen+1) { - newpos = songlen[esnum][eschn] + 1; + newpos = currentSonglen + 1; newcolumn = 1; } editmode = EDIT_ORDERLIST; - if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (!prevmouseb) && (newpos < songlen[esnum][eschn])) + if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (!prevmouseb) && (newpos < currentSonglen)) { if ((esmarkchn != newchn) || (newpos != esmarkend)) { @@ -763,7 +785,7 @@ void mousecommands(void) escolumn = newcolumn; } - if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (newpos < songlen[esnum][eschn])) esmarkend = newpos; + if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (newpos < currentSonglen)) esmarkend = newpos; } if (((!prevmouseb) || (mouseheld > HOLDDELAY)) && (mousey == dpos.orderlistY) && @@ -939,7 +961,16 @@ void mousecommands(void) if ((mousex >= 42) && (mousex <= 47)) save(); if ((mousex >= 49) && (mousex <= 57)) - relocator(); + { + if (numsids == 1) + { + relocator(); + } + else if (numsids == 2) + { + relocator_stereo(); + } + } if ((mousex >= 59) && (mousex <= 64)) onlinehelp(0,0); if ((mousex >= 66) && (mousex <= 72)) @@ -955,6 +986,8 @@ void generalcommands(void) int c; int maxChns = MAX_CHN; if (numsids == 1) maxChns = 3; + int visibleOrderlist = 14; + int currentSonglen = 0; switch(key) { @@ -1021,20 +1054,31 @@ void generalcommands(void) break; case ':': + if (numsids == 1) + { + visibleOrderlist = VISIBLEORDERLIST; + } for (c = 0; c < maxChns; c++) { - if (espos[c] < songlen[esnum][c]-1) + if (numsids == 1) + { + currentSonglen = songlen[esnum][c]; + } + else if (numsids == 2) + { + currentSonglen = songlen_stereo[esnum][c]; + } + if (espos[c] < currentSonglen-1) espos[c]++; - if (espos[c] - esview >= VISIBLEORDERLIST) + if (espos[c] - esview >= visibleOrderlist) { - esview = espos[c] - VISIBLEORDERLIST + 1; + esview = espos[c] - visibleOrderlist + 1; eseditpos = espos[c]; } } updateviewtopos(); rewindsong(); break; - } if (win_quitted) exitprogram = 1; switch(rawkey) @@ -1135,9 +1179,16 @@ void generalcommands(void) case KEY_F9: if (!shiftpressed) { - relocator(); + if (numsids == 1) + { + relocator(); + } + else if (numsids == 2) + { + relocator_stereo(); + } } - else if (numsids == 2) + else if (shiftpressed && (numsids == 2)) { monomode ^= 1; } diff --git a/src/goattrk2.h b/src/goattrk2.h index 254d5cd..f2dca16 100644 --- a/src/goattrk2.h +++ b/src/goattrk2.h @@ -67,6 +67,7 @@ extern unsigned adparam; extern unsigned ntsc; extern unsigned patterndispmode; extern unsigned sidaddress; +extern unsigned sid2address; extern unsigned finevibrato; extern unsigned optimizepulse; extern unsigned optimizerealtime; diff --git a/src/gorder.c b/src/gorder.c index d77e773..2254bd7 100644 --- a/src/gorder.c +++ b/src/gorder.c @@ -24,13 +24,13 @@ int esmarkend; int enpos; void orderlistcommands(void); +void orderlistcommands_stereo(void); void namecommands(void); void orderlistcommands(void) { int c, scrrep; - int maxChns = MAX_CHN; - if (numsids == 1) maxChns = 3; + int maxChns = 3; if (hexnybble >= 0) { @@ -410,6 +410,390 @@ void orderlistcommands(void) } } +void orderlistcommands_stereo(void) +{ + int c, scrrep; + int maxChns = MAX_CHN; + int visibleOrderlist = 14; + + if (hexnybble >= 0) + { + if (eseditpos != songlen_stereo[esnum][eschn]) + { + switch(escolumn) + { + case 0: + songorder_stereo[esnum][eschn][eseditpos] &= 0x0f; + songorder_stereo[esnum][eschn][eseditpos] |= hexnybble << 4; + if (eseditpos < songlen_stereo[esnum][eschn]) + { + if (songorder_stereo[esnum][eschn][eseditpos] >= MAX_PATT) + songorder_stereo[esnum][eschn][eseditpos] = MAX_PATT - 1; + } + else + { + if (songorder_stereo[esnum][eschn][eseditpos] >= MAX_SONGLEN) + songorder_stereo[esnum][eschn][eseditpos] = MAX_SONGLEN - 1; + } + break; + + case 1: + songorder_stereo[esnum][eschn][eseditpos] &= 0xf0; + if ((songorder_stereo[esnum][eschn][eseditpos] & 0xf0) == 0xd0) + { + hexnybble--; + if (hexnybble < 0) hexnybble = 0xf; + } + if ((songorder_stereo[esnum][eschn][eseditpos] & 0xf0) == 0xe0) + { + hexnybble = 16 - hexnybble; + hexnybble &= 0xf; + } + songorder_stereo[esnum][eschn][eseditpos] |= hexnybble; + + if (eseditpos < songlen_stereo[esnum][eschn]) + { + if (songorder_stereo[esnum][eschn][eseditpos] == LOOPSONG) + songorder_stereo[esnum][eschn][eseditpos] = LOOPSONG-1; + if (songorder_stereo[esnum][eschn][eseditpos] == TRANSDOWN) + songorder_stereo[esnum][eschn][eseditpos] = TRANSDOWN+0x0f; + } + else + { + if (songorder_stereo[esnum][eschn][eseditpos] >= MAX_SONGLEN) + songorder_stereo[esnum][eschn][eseditpos] = MAX_SONGLEN - 1; + } + break; + } + escolumn++; + if (escolumn > 1) + { + escolumn = 0; + if (eseditpos < (songlen_stereo[esnum][eschn]+1)) + { + eseditpos++; + if (eseditpos == songlen_stereo[esnum][eschn]) eseditpos++; + } + } + } + } + + switch(key) + { + case 'R': + if (eseditpos < songlen_stereo[esnum][eschn]) + { + songorder_stereo[esnum][eschn][eseditpos] = REPEAT + 0x01; + escolumn = 1; + } + break; + + case '+': + if (eseditpos < songlen_stereo[esnum][eschn]) + { + songorder_stereo[esnum][eschn][eseditpos] = TRANSUP; + escolumn = 1; + } + break; + + case '-': + if (eseditpos < songlen_stereo[esnum][eschn]) + { + songorder_stereo[esnum][eschn][eseditpos] = TRANSDOWN + 0x0F; + escolumn = 1; + } + break; + + case '>': + case ')': + case ']': + nextsong(); + break; + + case '<': + case '(': + case '[': + prevsong(); + break; + } + switch(rawkey) + { + case KEY_1: + case KEY_2: + case KEY_3: + if (shiftpressed) + { + int schn = eschn; + int tchn = 0; + + esmarkchn = -1; + if (rawkey == KEY_1) tchn = 0; + if (rawkey == KEY_2) tchn = 1; + if (rawkey == KEY_3) tchn = 2; + if (schn != tchn) + { + int lentemp = songlen_stereo[esnum][schn]; + songlen_stereo[esnum][schn] = songlen_stereo[esnum][tchn]; + songlen_stereo[esnum][tchn] = lentemp; + + for (c = 0; c < MAX_SONGLEN+2; c++) + { + unsigned char temp = songorder_stereo[esnum][schn][c]; + songorder_stereo[esnum][schn][c] = songorder_stereo[esnum][tchn][c]; + songorder_stereo[esnum][tchn][c] = temp; + } + } + } + break; + + case KEY_X: + if (shiftpressed) + { + if (esmarkchn != -1) + { + int d = 0; + + eschn = esmarkchn; + if (esmarkstart <= esmarkend) + { + eseditpos = esmarkstart; + for (c = esmarkstart; c <= esmarkend; c++) + trackcopybuffer[d++] = songorder_stereo[esnum][eschn][c]; + trackcopyrows = d; + } + else + { + eseditpos = esmarkend; + for (c = esmarkend; c <= esmarkstart; c++) + trackcopybuffer[d++] = songorder_stereo[esnum][eschn][c]; + trackcopyrows = d; + } + if (trackcopyrows == songlen_stereo[esnum][eschn]) + { + trackcopywhole = 1; + trackcopyrpos = songorder_stereo[esnum][eschn][songlen_stereo[esnum][eschn]+1]; + } + else trackcopywhole = 0; + for (c = 0; c < trackcopyrows; c++) deleteorder_stereo(); + esmarkchn = -1; + } + } + break; + + case KEY_C: + if (shiftpressed) + { + if (esmarkchn != -1) + { + int d = 0; + if (esmarkstart <= esmarkend) + { + for (c = esmarkstart; c <= esmarkend; c++) + trackcopybuffer[d++] = songorder_stereo[esnum][eschn][c]; + trackcopyrows = d; + } + else + { + for (c = esmarkend; c <= esmarkstart; c++) + trackcopybuffer[d++] = songorder_stereo[esnum][eschn][c]; + trackcopyrows = d; + } + if (trackcopyrows == songlen_stereo[esnum][eschn]) + { + trackcopywhole = 1; + trackcopyrpos = songorder_stereo[esnum][eschn][songlen_stereo[esnum][eschn]+1]; + } + else trackcopywhole = 0; + esmarkchn = -1; + } + } + break; + + case KEY_V: + if (shiftpressed) + { + int oldlen = songlen_stereo[esnum][eschn]; + + if (eseditpos < songlen_stereo[esnum][eschn]) + { + for (c = trackcopyrows-1; c >= 0; c--) + insertorder_stereo(trackcopybuffer[c]); + } + else + { + for (c = 0; c < trackcopyrows; c++) + insertorder_stereo(trackcopybuffer[c]); + } + if ((trackcopywhole) && (!oldlen)) + songorder_stereo[esnum][eschn][songlen_stereo[esnum][eschn]+1] = trackcopyrpos; + } + break; + + case KEY_L: + if (shiftpressed) + { + if (esmarkchn == -1) + { + esmarkchn = eschn; + esmarkstart = 0; + esmarkend = songlen_stereo[esnum][eschn]-1; + } + else esmarkchn = -1; + } + break; + + + case KEY_SPACE: + if (!shiftpressed) + { + if (eseditpos < songlen_stereo[esnum][eschn]) espos[eschn] = eseditpos; + if (esend[eschn] < espos[eschn]) esend[eschn] = 0; + } + else + { + for (c = 0; c < maxChns; c++) + { + if (eseditpos < songlen_stereo[esnum][c]) espos[c] = eseditpos; + if (esend[c] < espos[c]) esend[c] = 0; + } + } + break; + + case KEY_BACKSPACE: + if (!shiftpressed) + { + if ((esend[eschn] != eseditpos) && (eseditpos > espos[eschn])) + { + if (eseditpos < songlen_stereo[esnum][eschn]) esend[eschn] = eseditpos; + } + else esend[eschn] = 0; + } + else + { + if ((esend[eschn] != eseditpos) && (eseditpos > espos[eschn])) + { + for (c = 0; c < maxChns; c++) + { + if (eseditpos < songlen_stereo[esnum][c]) esend[c] = eseditpos; + } + } + else + { + for (c = 0; c < maxChns; c++) esend[c] = 0; + } + } + break; + + case KEY_ENTER: + if (eseditpos < songlen_stereo[esnum][eschn]) + { + if (!shiftpressed) + { + if (songorder_stereo[esnum][eschn][eseditpos] < MAX_PATT) + epnum[eschn] = songorder_stereo[esnum][eschn][eseditpos]; + } + else + { + int c, d; + + for (c = 0; c < maxChns; c++) + { + int start; + + if (eseditpos != espos[eschn]) start = eseditpos; + else start = espos[c]; + + for (d = start; d < songlen_stereo[esnum][c]; d++) + { + if (songorder_stereo[esnum][c][d] < MAX_PATT) + { + epnum[c] = songorder_stereo[esnum][c][d]; + break; + } + } + } + } + epmarkchn = -1; + } + epchn = eschn; + epcolumn = 0; + eppos = 0; + epview = - VISIBLEPATTROWS/2; + editmode = EDIT_PATTERN; + if (epchn == epmarkchn) epmarkchn = -1; + break; + + case KEY_DEL: + esmarkchn = -1; + deleteorder_stereo(); + break; + + case KEY_INS: + esmarkchn = -1; + insertorder_stereo(0); + break; + + case KEY_HOME: + if (songlen_stereo[esnum][eschn]) + { + while ((eseditpos != 0) || (escolumn != 0)) orderleft_stereo(); + } + break; + + case KEY_END: + while (eseditpos != songlen_stereo[esnum][eschn]+1) orderright_stereo(); + break; + + case KEY_PGUP: + for (scrrep = PGUPDNREPEAT * 2; scrrep; scrrep--) + orderleft_stereo(); + break; + + case KEY_PGDN: + for (scrrep = PGUPDNREPEAT * 2; scrrep; scrrep--) + orderright_stereo(); + break; + + case KEY_LEFT: + orderleft_stereo(); + break; + + case KEY_RIGHT: + orderright_stereo(); + break; + + case KEY_UP: + eschn--; + if (eschn < 0) eschn = maxChns - 1; + if ((eseditpos == songlen_stereo[esnum][eschn]) || (eseditpos > songlen_stereo[esnum][eschn]+1)) + { + eseditpos = songlen_stereo[esnum][eschn]+1; + escolumn = 0; + } + if (shiftpressed) esmarkchn = -1; + break; + + case KEY_DOWN: + eschn++; + if (eschn >= maxChns) eschn = 0; + if ((eseditpos == songlen_stereo[esnum][eschn]) || (eseditpos > songlen_stereo[esnum][eschn]+1)) + { + eseditpos = songlen_stereo[esnum][eschn]+1; + escolumn = 0; + } + if (shiftpressed) esmarkchn = -1; + break; + } + if (eseditpos - esview < 0) + { + esview = eseditpos; + } + if (eseditpos - esview >= visibleOrderlist) + { + esview = eseditpos - visibleOrderlist + 1; + } +} + void namecommands(void) { switch(rawkey) @@ -481,6 +865,46 @@ void insertorder(unsigned char byte) } } +void insertorder_stereo(unsigned char byte) +{ + if ((songlen_stereo[esnum][eschn] - eseditpos)-1 >= 0) + { + int len; + if (songlen_stereo[esnum][eschn] < MAX_SONGLEN) + { + len = songlen_stereo[esnum][eschn]+1; + songorder_stereo[esnum][eschn][len+1] = + songorder_stereo[esnum][eschn][len]; + songorder_stereo[esnum][eschn][len] = LOOPSONG; + if (len) songorder_stereo[esnum][eschn][len-1] = byte; + countthispattern(); + } + memmove(&songorder_stereo[esnum][eschn][eseditpos+1], + &songorder_stereo[esnum][eschn][eseditpos], + (songlen_stereo[esnum][eschn] - eseditpos)-1); + songorder_stereo[esnum][eschn][eseditpos] = byte; + len = songlen_stereo[esnum][eschn]+1; + if ((songorder_stereo[esnum][eschn][len] > eseditpos) && + (songorder_stereo[esnum][eschn][len] < (len-2))) + songorder_stereo[esnum][eschn][len]++; + } + else + { + if (eseditpos > songlen_stereo[esnum][eschn]) + { + if (songlen_stereo[esnum][eschn] < MAX_SONGLEN) + { + songorder_stereo[esnum][eschn][eseditpos+1] = + songorder_stereo[esnum][eschn][eseditpos]; + songorder_stereo[esnum][eschn][eseditpos] = LOOPSONG; + if (eseditpos) songorder_stereo[esnum][eschn][eseditpos-1] = byte; + countthispattern(); + eseditpos = songlen_stereo[esnum][eschn]+1; + } + } + } +} + void deleteorder(void) { if ((songlen[esnum][eschn] - eseditpos)-1 >= 0) @@ -521,6 +945,46 @@ void deleteorder(void) } } +void deleteorder_stereo(void) +{ + if ((songlen_stereo[esnum][eschn] - eseditpos)-1 >= 0) + { + int len; + memmove(&songorder_stereo[esnum][eschn][eseditpos], + &songorder_stereo[esnum][eschn][eseditpos+1], + (songlen_stereo[esnum][eschn] - eseditpos)-1); + songorder_stereo[esnum][eschn][songlen_stereo[esnum][eschn]-1] = 0x00; + if (songlen_stereo[esnum][eschn] > 0) + { + songorder_stereo[esnum][eschn][songlen_stereo[esnum][eschn]-1] = + songorder_stereo[esnum][eschn][songlen_stereo[esnum][eschn]]; + songorder_stereo[esnum][eschn][songlen_stereo[esnum][eschn]] = + songorder_stereo[esnum][eschn][songlen_stereo[esnum][eschn]+1]; + countthispattern(); + } + if (eseditpos == songlen_stereo[esnum][eschn]) eseditpos++; + len = songlen_stereo[esnum][eschn]+1; + if ((songorder_stereo[esnum][eschn][len] > eseditpos) && + (songorder_stereo[esnum][eschn][len] > 0)) + songorder_stereo[esnum][eschn][len]--; + } + else + { + if (eseditpos > songlen_stereo[esnum][eschn]) + { + if (songlen_stereo[esnum][eschn] > 0) + { + songorder_stereo[esnum][eschn][songlen_stereo[esnum][eschn]-1] = + songorder_stereo[esnum][eschn][songlen_stereo[esnum][eschn]]; + songorder_stereo[esnum][eschn][songlen_stereo[esnum][eschn]] = + songorder_stereo[esnum][eschn][songlen_stereo[esnum][eschn]+1]; + countthispattern(); + eseditpos = songlen_stereo[esnum][eschn]+1; + } + } + } +} + void orderleft(void) { if ((shiftpressed) && (eseditpos < songlen[esnum][eschn])) @@ -550,6 +1014,34 @@ void orderleft(void) if ((shiftpressed) && (eseditpos < songlen[esnum][eschn])) esmarkend = eseditpos; } +void orderleft_stereo(void) +{ + if ((shiftpressed) && (eseditpos < songlen_stereo[esnum][eschn])) + { + if ((esmarkchn != eschn) || (eseditpos != esmarkend)) + { + esmarkchn = eschn; + esmarkstart = esmarkend = eseditpos; + } + } + escolumn--; + if (escolumn < 0) + { + if (eseditpos > 0) + { + eseditpos--; + if (eseditpos == songlen_stereo[esnum][eschn]) eseditpos--; + escolumn = 1; + if (eseditpos < 0) + { + eseditpos = 1; + escolumn = 0; + } + } + else escolumn = 0; + } + if ((shiftpressed) && (eseditpos < songlen_stereo[esnum][eschn])) esmarkend = eseditpos; +} void orderright(void) { if ((shiftpressed) && (eseditpos < songlen[esnum][eschn])) @@ -574,6 +1066,30 @@ void orderright(void) if ((shiftpressed) && (eseditpos < songlen[esnum][eschn])) esmarkend = eseditpos; } +void orderright_stereo(void) +{ + if ((shiftpressed) && (eseditpos < songlen_stereo[esnum][eschn])) + { + if ((esmarkchn != eschn) || (eseditpos != esmarkend)) + { + esmarkchn = eschn; + esmarkstart = esmarkend = eseditpos; + } + } + escolumn++; + if (escolumn > 1) + { + escolumn = 0; + if (eseditpos < (songlen_stereo[esnum][eschn]+1)) + { + eseditpos++; + if (eseditpos == songlen_stereo[esnum][eschn]) eseditpos++; + } + else escolumn = 1; + } + if ((shiftpressed) && (eseditpos < songlen_stereo[esnum][eschn])) esmarkend = eseditpos; +} + void nextsong(void) { esnum++; @@ -593,6 +1109,15 @@ void songchange(void) int c; int maxChns = MAX_CHN; if (numsids == 1) maxChns = 3; + int currentSonglen = 0; + if (numsids == 1) + { + currentSonglen = songlen[esnum][eschn]; + } + else if (numsids == 2) + { + currentSonglen = songlen_stereo[esnum][eschn]; + } for (c = 0; c < maxChns; c++) { @@ -605,7 +1130,7 @@ void songchange(void) eppos = 0; epview = - VISIBLEPATTROWS/2; eseditpos = 0; - if (eseditpos == songlen[esnum][eschn]) eseditpos++; + if (eseditpos == currentSonglen) eseditpos++; esview = 0; epmarkchn = -1; esmarkchn = -1; @@ -617,14 +1142,32 @@ void updateviewtopos(void) int c, d; int maxChns = MAX_CHN; if (numsids == 1) maxChns = 3; + int currentSonglen = 0; + int currentSongorder = 0; for (c = 0; c < maxChns; c++) { - for (d = espos[c]; d < songlen[esnum][c]; d++) + if (numsids == 1) + { + currentSonglen = songlen[esnum][c]; + } + else if (numsids == 2) + { + currentSonglen = songlen_stereo[esnum][c]; + } + for (d = espos[c]; d < currentSonglen; d++) { - if (songorder[esnum][c][d] < MAX_PATT) + if (numsids == 1) + { + currentSongorder = songorder[esnum][c][d]; + } + else if (numsids == 2) + { + currentSongorder = songorder_stereo[esnum][c][d]; + } + if (currentSongorder < MAX_PATT) { - epnum[c] = songorder[esnum][c][d]; + epnum[c] = currentSongorder; break; } } diff --git a/src/gorder.h b/src/gorder.h index 1e82161..5440ad5 100644 --- a/src/gorder.h +++ b/src/gorder.h @@ -17,6 +17,7 @@ extern int enpos; void updateviewtopos(void); void orderlistcommands(void); +void orderlistcommands_stereo(void); void namecommands(void); void nextsong(void); void prevsong(void); @@ -25,5 +26,9 @@ void orderleft(void); void orderright(void); void deleteorder(void); void insertorder(unsigned char byte); +void orderleft_stereo(void); +void orderright_stereo(void); +void deleteorder_stereo(void); +void insertorder_stereo(unsigned char byte); #endif diff --git a/src/gplay.c b/src/gplay.c index e2e9431..7b64831 100644 --- a/src/gplay.c +++ b/src/gplay.c @@ -40,6 +40,11 @@ unsigned char filtertype = 0; unsigned char filtercutoff = 0; unsigned char filtertime = 0; unsigned char filterptr = 0; +unsigned char filter2ctrl = 0; +unsigned char filter2type = 0; +unsigned char filter2cutoff = 0; +unsigned char filter2time = 0; +unsigned char filter2ptr = 0; unsigned char funktable[2]; unsigned char masterfader = 0x0f; int psnum = 0; @@ -48,6 +53,7 @@ int lastsonginit = 0; int startpattpos = 0; void sequencer(int c, CHN *cptr); +void sequencer_stereo(int c, CHN *cptr); void initchannels(void) { @@ -131,8 +137,16 @@ void playtestnote(int note, int ins, int chnnum) chn[chnnum].gate = 0xfe; // Keyoff if (!(instr[ins].gatetimer & 0x80)) { - sidreg[0x5+chnnum*7] = adparam>>8; // Hardrestart - sidreg[0x6+chnnum*7] = adparam&0xff; + if (chnnum < 3) + { + sidreg[0x5+chnnum*7] = adparam>>8; // Hardrestart + sidreg[0x6+chnnum*7] = adparam&0xff; + } + else + { + sidreg2[0x5+(chnnum-3)*7] = adparam>>8; // Hardrestart + sidreg2[0x6+(chnnum-3)*7] = adparam&0xff; + } } } @@ -165,8 +179,7 @@ void playroutine(void) INSTR *iptr; CHN *cptr = &chn[0]; int c; - int maxChns = MAX_CHN; - if (numsids == 1) maxChns = 3; + int maxChns = 3; if (songinit == PLAY_STOP) followplay = 0; @@ -1005,10 +1018,1025 @@ void sequencer(int c, CHN *cptr) } if (cptr->pattptr >= (pattlen[cptr->pattnum] * 4)) cptr->pattptr = 0; - + // Check for playback endpos if ((lastsonginit != PLAY_BEGINNING) && (esend[c] > 0) && (esend[c] > espos[c]) && (cptr->songptr > esend[c]) && (espos[c] < songlen[psnum][c])) cptr->songptr = espos[c]; } SEQDONE: {} } + +/* ========================================================================== */ + +void playroutine_stereo(void) +{ + INSTR *iptr; + CHN *cptr = &chn[0]; + int c; + + if (songinit == PLAY_STOP) + followplay = 0; + + if ((songinit > 0) && (songinit < PLAY_STOPPED)) + { + lastsonginit = songinit; + + filterctrl = 0; + filterptr = 0; + filter2ctrl = 0; + filter2ptr = 0; + + resettime(); + + if ((songinit == 0x02) || (songinit == 0x03)) + { + for (c = 0; c< MAX_CHN; c++) + { + if (espos[c] >= songlen_stereo[psnum][c]) + songinit = 0x01; + } + } + + for (c = 0; c < MAX_CHN; c++) + { + cptr->songptr = 0; + cptr->command = 0; + cptr->cmddata = 0; + cptr->newcommand = 0; + cptr->newcmddata = 0; + cptr->advance = 1; + cptr->wave = 0; + cptr->ptr[WTBL] = 0; + cptr->newnote = 0; + cptr->repeat = 0; + if (multiplier) + cptr->tick = 6*multiplier-1; + else + cptr->tick = 6-1; + cptr->gatetimer = instr[1].gatetimer & 0x3f; + cptr->pattptr = 0x7fffffff; + if (cptr->tempo < 2) cptr->tempo = 0; + + switch (songinit) + { + case PLAY_BEGINNING: + if (multiplier) + { + funktable[0] = 9*multiplier-1; + funktable[1] = 6*multiplier-1; + cptr->tempo = 6*multiplier-1; + } + else + { + funktable[0] = 9-1; + funktable[1] = 6-1; + cptr->tempo = 6-1; + } + if ((instr[MAX_INSTR-1].ad >= 2) && (!(instr[MAX_INSTR-1].ptr[WTBL]))) + cptr->tempo = instr[MAX_INSTR-1].ad - 1; + cptr->trans = 0; + cptr->instr = 1; + sequencer_stereo(c, cptr); + break; + + case PLAY_PATTERN: + cptr->advance = 0; + cptr->pattptr = startpattpos * 4; + cptr->pattnum = epnum[c]; + if (cptr->pattptr >= (pattlen[cptr->pattnum] * 4)) + cptr->pattptr = 0; + break; + + case PLAY_POS: + cptr->songptr = espos[c]; + sequencer_stereo(c, cptr); + break; + } + cptr++; + } + if (songinit != PLAY_STOP) + songinit = 0; + else + songinit = PLAY_STOPPED; + if ((!songlen_stereo[psnum][0]) || (!songlen_stereo[psnum][1]) || (!songlen_stereo[psnum][2]) || + (!songlen_stereo[psnum][3]) || (!songlen_stereo[psnum][4]) || (!songlen_stereo[psnum][5])) + songinit = PLAY_STOPPED; // Zero length song + + startpattpos = 0; + } + else + { + if (filterptr) + { + // Filter jump + if (ltable[FTBL][filterptr-1] == 0xff) + { + filterptr = rtable[FTBL][filterptr-1]; + if (!filterptr) goto FILTERSTOP_S; + } + + if (!filtertime) + { + // Filter set + if (ltable[FTBL][filterptr-1] >= 0x80) + { + filtertype = ltable[FTBL][filterptr-1] & 0x70; + filterctrl = rtable[FTBL][filterptr-1]; + filterptr++; + // Can be combined with cutoff set + if (ltable[FTBL][filterptr-1] == 0x00) + { + filtercutoff = rtable[FTBL][filterptr-1]; + filterptr++; + } + } + else + { + // New modulation step + if (ltable[FTBL][filterptr-1]) + filtertime = ltable[FTBL][filterptr-1]; + else + { + // Cutoff set + filtercutoff = rtable[FTBL][filterptr-1]; + filterptr++; + } + } + } + // Filter modulation + if (filtertime) + { + filtercutoff += rtable[FTBL][filterptr-1]; + filtertime--; + if (!filtertime) filterptr++; + } + } +FILTERSTOP_S: + sidreg[0x15] = 0x00; + sidreg[0x16] = filtercutoff; + sidreg[0x17] = filterctrl; + sidreg[0x18] = filtertype | masterfader; + + if (filter2ptr) + { + // Filter jump + if (ltable[FTBL][filter2ptr-1] == 0xff) + { + filter2ptr = rtable[FTBL][filter2ptr-1]; + if (!filter2ptr) goto FILTER2STOP_S; + } + + if (!filter2time) + { + // Filter set + if (ltable[FTBL][filter2ptr-1] >= 0x80) + { + filter2type = ltable[FTBL][filter2ptr-1] & 0x70; + filter2ctrl = rtable[FTBL][filter2ptr-1]; + filter2ptr++; + // Can be combined with cutoff set + if (ltable[FTBL][filter2ptr-1] == 0x00) + { + filter2cutoff = rtable[FTBL][filter2ptr-1]; + filter2ptr++; + } + } + else + { + // New modulation step + if (ltable[FTBL][filter2ptr-1]) + filter2time = ltable[FTBL][filter2ptr-1]; + else + { + // Cutoff set + filter2cutoff = rtable[FTBL][filter2ptr-1]; + filter2ptr++; + } + } + } + // Filter modulation + if (filter2time) + { + filter2cutoff += rtable[FTBL][filter2ptr-1]; + filter2time--; + if (!filter2time) filter2ptr++; + } + } + +FILTER2STOP_S: + sidreg2[0x15] = 0x00; + sidreg2[0x16] = filter2cutoff; + sidreg2[0x17] = filter2ctrl; + sidreg2[0x18] = filter2type | masterfader; + + for (c = 0; c < MAX_CHN; c++) + { + iptr = &instr[cptr->instr]; + + // Reset tempo in jammode + if ((songinit == PLAY_STOPPED) && (cptr->tempo < 2)) + { + if (multiplier) + cptr->tempo = 6*multiplier-1; + else + cptr->tempo = 6-1; + } + + // Decrease tick + cptr->tick--; + if (!cptr->tick) goto TICK0_S; + + // Tick N + // Reload counter + if (cptr->tick >= 0x80) + { + if (cptr->tempo >= 2) + cptr->tick = cptr->tempo; + else + { + // Set funktempo, switch between 2 values + cptr->tick = funktable[cptr->tempo]; + cptr->tempo ^= 1; + } + // Check for illegally high gatetimer and stop the song in this case + if (chn->gatetimer > cptr->tick) + stopsong(); + } + goto WAVEEXEC_S; + + // Tick 0 +TICK0_S: + // Advance in sequencer + sequencer_stereo(c, cptr); + + // Get gatetimer compare-value + cptr->gatetimer = iptr->gatetimer & 0x3f; + + // New note init + if (cptr->newnote) + { + cptr->note = cptr->newnote-FIRSTNOTE; + cptr->command = 0; + cptr->vibdelay = iptr->vibdelay; + cptr->cmddata = iptr->ptr[STBL]; + if (cptr->newcommand != CMD_TONEPORTA) + { + if (iptr->firstwave) + { + if (iptr->firstwave >= 0xfe) cptr->gate = iptr->firstwave; + else + { + cptr->wave = iptr->firstwave; + cptr->gate = 0xff; + } + } + + + cptr->ptr[WTBL] = iptr->ptr[WTBL]; + + if (cptr->ptr[WTBL]) + { + // Stop the song in case of jumping into a jump + if (ltable[WTBL][cptr->ptr[WTBL]-1] == 0xff) + stopsong(); + } + if (iptr->ptr[PTBL]) + { + cptr->ptr[PTBL] = iptr->ptr[PTBL]; + cptr->pulsetime = 0; + if (cptr->ptr[PTBL]) + { + // Stop the song in case of jumping into a jump + if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff) + stopsong(); + } + } + if (iptr->ptr[FTBL]) + { + if (c < 3) + { + filterptr = iptr->ptr[FTBL]; + filtertime = 0; + if (filterptr) + { + // Stop the song in case of jumping into a jump + if (ltable[FTBL][filterptr-1] == 0xff) + stopsong(); + } + } + else + { + filter2ptr = iptr->ptr[FTBL]; + filter2time = 0; + if (filter2ptr) + { + // Stop the song in case of jumping into a jump + if (ltable[FTBL][filter2ptr-1] == 0xff) + stopsong(); + } + } + } + if (c < 3) + { + sidreg[0x5+7*c] = iptr->ad; + sidreg[0x6+7*c] = iptr->sr; + } + else + { + sidreg2[0x5+7*(c-3)] = iptr->ad; + sidreg2[0x6+7*(c-3)] = iptr->sr; + } + } + } + + // Tick 0 effects + + switch (cptr->newcommand) + { + case CMD_DONOTHING: + cptr->command = 0; + cptr->cmddata = iptr->ptr[STBL]; + break; + + case CMD_PORTAUP: + case CMD_PORTADOWN: + cptr->vibtime = 0; + cptr->command = cptr->newcommand; + cptr->cmddata = cptr->newcmddata; + break; + + case CMD_TONEPORTA: + case CMD_VIBRATO: + cptr->command = cptr->newcommand; + cptr->cmddata = cptr->newcmddata; + break; + + case CMD_SETAD: + if (c < 3) + sidreg[0x5+7*c] = cptr->newcmddata; + else + sidreg2[0x5+7*(c-3)] = cptr->newcmddata; + break; + + case CMD_SETSR: + if (c < 3) + sidreg[0x6+7*c] = cptr->newcmddata; + else + sidreg2[0x6+7*(c-3)] = cptr->newcmddata; + break; + + case CMD_SETWAVE: + cptr->wave = cptr->newcmddata; + break; + + case CMD_SETWAVEPTR: + cptr->ptr[WTBL] = cptr->newcmddata; + cptr->wavetime = 0; + if (cptr->ptr[WTBL]) + { + // Stop the song in case of jumping into a jump + if (ltable[WTBL][cptr->ptr[WTBL]-1] == 0xff) + stopsong(); + } + break; + + case CMD_SETPULSEPTR: + cptr->ptr[PTBL] = cptr->newcmddata; + cptr->pulsetime = 0; + if (cptr->ptr[PTBL]) + { + // Stop the song in case of jumping into a jump + if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff) + stopsong(); + } + break; + + case CMD_SETFILTERPTR: + if (c < 3) + { + filterptr = cptr->newcmddata; + filtertime = 0; + if (filterptr) + { + // Stop the song in case of jumping into a jump + if (ltable[FTBL][filterptr-1] == 0xff) + stopsong(); + } + } + else + { + filter2ptr = cptr->newcmddata; + filter2time = 0; + if (filter2ptr) + { + // Stop the song in case of jumping into a jump + if (ltable[FTBL][filter2ptr-1] == 0xff) + stopsong(); + } + } + break; + + case CMD_SETFILTERCTRL: + if (c < 3) + { + filterctrl = cptr->newcmddata; + if (!filterctrl) filterptr = 0; + } + else + { + filter2ctrl = cptr->newcmddata; + if (!filter2ctrl) filter2ptr = 0; + } + break; + + case CMD_SETFILTERCUTOFF: + if (c < 3) + filtercutoff = cptr->newcmddata; + else + filter2cutoff = cptr->newcmddata; + break; + + case CMD_SETMASTERVOL: + if (cptr->newcmddata < 0x10) + masterfader = cptr->newcmddata; + break; + + case CMD_FUNKTEMPO: + if (cptr->newcmddata) + { + funktable[0] = ltable[STBL][cptr->newcmddata-1]-1; + funktable[1] = rtable[STBL][cptr->newcmddata-1]-1; + } + { + int d; + for (d = 0; d < MAX_CHN; d++) + chn[d].tempo = 0; + } + break; + + case CMD_SETTEMPO: + { + unsigned char newtempo = cptr->newcmddata & 0x7f; + + if (newtempo >= 3) newtempo--; + if (cptr->newcmddata >= 0x80) + cptr->tempo = newtempo; + else + { + int d; + for (d = 0; d < MAX_CHN; d++) + chn[d].tempo = newtempo; + } + } + break; + } + if (cptr->newnote) + { + cptr->newnote = 0; + if (cptr->newcommand != CMD_TONEPORTA) goto NEXTCHN_S; + } + +WAVEEXEC_S: + if (cptr->ptr[WTBL]) + { + unsigned char wave = ltable[WTBL][cptr->ptr[WTBL]-1]; + unsigned char note = rtable[WTBL][cptr->ptr[WTBL]-1]; + + if (wave > WAVELASTDELAY) + { + // Normal waveform values + if (wave < WAVESILENT) cptr->wave = wave; + // Values without waveform selected + if ((wave >= WAVESILENT) && (wave <= WAVELASTSILENT)) cptr->wave = wave & 0xf; + // Command execution from wavetable + if ((wave >= WAVECMD) && (wave <= WAVELASTCMD)) + { + unsigned char param = rtable[WTBL][cptr->ptr[WTBL]-1]; + switch (wave & 0xf) + { + case CMD_DONOTHING: + case CMD_SETWAVEPTR: + case CMD_FUNKTEMPO: + stopsong(); + break; + + case CMD_PORTAUP: + { + unsigned short speed = 0; + if (param) + { + speed = (ltable[STBL][param-1] << 8) | rtable[STBL][param-1]; + } + if (speed >= 0x8000) + { + speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); + speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); + speed >>= rtable[STBL][param-1]; + } + cptr->freq += speed; + } + break; + + case CMD_PORTADOWN: + { + unsigned short speed = 0; + if (param) + { + speed = (ltable[STBL][param-1] << 8) | rtable[STBL][param-1]; + } + if (speed >= 0x8000) + { + speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); + speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); + speed >>= rtable[STBL][param-1]; + } + cptr->freq -= speed; + } + break; + + case CMD_TONEPORTA: + { + unsigned short targetfreq = freqtbllo[cptr->note] | (freqtblhi[cptr->note] << 8); + unsigned short speed = 0; + + if (!param) + { + cptr->freq = targetfreq; + cptr->vibtime = 0; + } + else + { + speed = (ltable[STBL][param-1] << 8) | rtable[STBL][param-1]; + if (speed >= 0x8000) + { + speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); + speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); + speed >>= rtable[STBL][param-1]; + } + if (cptr->freq < targetfreq) + { + cptr->freq += speed; + if (cptr->freq > targetfreq) + { + cptr->freq = targetfreq; + cptr->vibtime = 0; + } + } + if (cptr->freq > targetfreq) + { + cptr->freq -= speed; + if (cptr->freq < targetfreq) + { + cptr->freq = targetfreq; + cptr->vibtime = 0; + } + } + } + } + break; + + case CMD_VIBRATO: + { + unsigned short speed = 0; + unsigned char cmpvalue = 0; + + if (param) + { + cmpvalue = ltable[STBL][param-1]; + speed = rtable[STBL][param-1]; + } + if (cmpvalue >= 0x80) + { + cmpvalue &= 0x7f; + speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); + speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); + speed >>= rtable[STBL][param-1]; + } + + if ((cptr->vibtime < 0x80) && (cptr->vibtime > cmpvalue)) + cptr->vibtime ^= 0xff; + cptr->vibtime += 0x02; + if (cptr->vibtime & 0x01) + cptr->freq -= speed; + else + cptr->freq += speed; + } + break; + + case CMD_SETAD: + if (c < 3) + sidreg[0x5+7*c] = param; + else + sidreg2[0x5+7*(c-3)] = param; + break; + + case CMD_SETSR: + if (c < 3) + sidreg[0x6+7*c] = param; + else + sidreg2[0x6+7*(c-3)] = param; + break; + + case CMD_SETWAVE: + cptr->wave = param; + break; + + case CMD_SETPULSEPTR: + cptr->ptr[PTBL] = param; + cptr->pulsetime = 0; + if (cptr->ptr[PTBL]) + { + // Stop the song in case of jumping into a jump + if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff) + stopsong(); + } + break; + + case CMD_SETFILTERPTR: + if (c < 3) + { + filterptr = param; + filtertime = 0; + if (filterptr) + { + // Stop the song in case of jumping into a jump + if (ltable[FTBL][filterptr-1] == 0xff) + stopsong(); + } + } + else + { + filter2ptr = param; + filter2time = 0; + if (filter2ptr) + { + // Stop the song in case of jumping into a jump + if (ltable[FTBL][filter2ptr-1] == 0xff) + stopsong(); + } + } + break; + + case CMD_SETFILTERCTRL: + if (c < 3) + { + filterctrl = param; + if (!filterctrl) filterptr = 0; + } + else + { + filter2ctrl = param; + if (!filter2ctrl) filter2ptr = 0; + } + break; + + case CMD_SETFILTERCUTOFF: + if (c < 3) + filtercutoff = param; + else + filter2cutoff = param; + break; + + case CMD_SETMASTERVOL: + if (param < 0x10) + masterfader = param; + break; + } + } + } + else + { + // Wavetable delay + if (cptr->wavetime != wave) + { + cptr->wavetime++; + goto TICKNEFFECTS_S; + } + } + + cptr->wavetime = 0; + cptr->ptr[WTBL]++; + // Wavetable jump + if (ltable[WTBL][cptr->ptr[WTBL]-1] == 0xff) + { + cptr->ptr[WTBL] = rtable[WTBL][cptr->ptr[WTBL]-1]; + } + + if ((wave >= WAVECMD) && (wave <= WAVELASTCMD)) + goto PULSEEXEC_S; + + if (note != 0x80) + { + if (note < 0x80) + note += cptr->note; + note &= 0x7f; + cptr->freq = freqtbllo[note] | (freqtblhi[note]<<8); + cptr->vibtime = 0; + cptr->lastnote = note; + goto PULSEEXEC_S; + } + } + + // Tick N command +TICKNEFFECTS_S: + if ((!optimizerealtime) || (cptr->tick)) + { + switch(cptr->command) + { + case CMD_PORTAUP: + { + unsigned short speed = 0; + if (cptr->cmddata) + { + speed = (ltable[STBL][cptr->cmddata-1] << 8) | rtable[STBL][cptr->cmddata-1]; + } + if (speed >= 0x8000) + { + speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); + speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); + speed >>= rtable[STBL][cptr->cmddata-1]; + } + cptr->freq += speed; + } + break; + + case CMD_PORTADOWN: + { + unsigned short speed = 0; + if (cptr->cmddata) + { + speed = (ltable[STBL][cptr->cmddata-1] << 8) | rtable[STBL][cptr->cmddata-1]; + } + if (speed >= 0x8000) + { + speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); + speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); + speed >>= rtable[STBL][cptr->cmddata-1]; + } + cptr->freq -= speed; + } + break; + + case CMD_DONOTHING: + if ((!cptr->cmddata) || (!cptr->vibdelay)) + break; + if (cptr->vibdelay > 1) + { + cptr->vibdelay--; + break; + } + case CMD_VIBRATO: + { + unsigned short speed = 0; + unsigned char cmpvalue = 0; + + if (cptr->cmddata) + { + cmpvalue = ltable[STBL][cptr->cmddata-1]; + speed = rtable[STBL][cptr->cmddata-1]; + } + if (cmpvalue >= 0x80) + { + cmpvalue &= 0x7f; + speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); + speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); + speed >>= rtable[STBL][cptr->cmddata-1]; + } + + if ((cptr->vibtime < 0x80) && (cptr->vibtime > cmpvalue)) + cptr->vibtime ^= 0xff; + cptr->vibtime += 0x02; + if (cptr->vibtime & 0x01) + cptr->freq -= speed; + else + cptr->freq += speed; + } + break; + + case CMD_TONEPORTA: + { + unsigned short targetfreq = freqtbllo[cptr->note] | (freqtblhi[cptr->note] << 8); + unsigned short speed = 0; + + if (!cptr->cmddata) + { + cptr->freq = targetfreq; + cptr->vibtime = 0; + } + else + { + speed = (ltable[STBL][cptr->cmddata-1] << 8) | rtable[STBL][cptr->cmddata-1]; + if (speed >= 0x8000) + { + speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); + speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); + speed >>= rtable[STBL][cptr->cmddata-1]; + } + if (cptr->freq < targetfreq) + { + cptr->freq += speed; + if (cptr->freq > targetfreq) + { + cptr->freq = targetfreq; + cptr->vibtime = 0; + } + } + if (cptr->freq > targetfreq) + { + cptr->freq -= speed; + if (cptr->freq < targetfreq) + { + cptr->freq = targetfreq; + cptr->vibtime = 0; + } + } + } + } + break; + } + } + +PULSEEXEC_S: + if (optimizepulse) + { + if ((songinit != PLAY_STOPPED) && (cptr->tick == cptr->gatetimer)) goto GETNEWNOTES_S; + } + + if (cptr->ptr[PTBL]) + { + // Skip pulse when sequencer has been executed + if (optimizepulse) + { + if ((!cptr->tick) && (!cptr->pattptr)) goto NEXTCHN_S; + } + + // Pulsetable jump + if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff) + { + cptr->ptr[PTBL] = rtable[PTBL][cptr->ptr[PTBL]-1]; + if (!cptr->ptr[PTBL]) goto PULSEEXEC_S; + } + + if (!cptr->pulsetime) + { + // Set pulse + if (ltable[PTBL][cptr->ptr[PTBL]-1] >= 0x80) + { + cptr->pulse = (ltable[PTBL][cptr->ptr[PTBL]-1] & 0xf) << 8; + cptr->pulse |= rtable[PTBL][cptr->ptr[PTBL]-1]; + cptr->ptr[PTBL]++; + } + else + { + cptr->pulsetime = ltable[PTBL][cptr->ptr[PTBL]-1]; + } + } + // Pulse modulation + if (cptr->pulsetime) + { + unsigned char speed = rtable[PTBL][cptr->ptr[PTBL]-1]; + if (speed < 0x80) + { + cptr->pulse += speed; + cptr->pulse &= 0xfff; + } + else + { + cptr->pulse += speed; + cptr->pulse -= 0x100; + cptr->pulse &= 0xfff; + } + cptr->pulsetime--; + if (!cptr->pulsetime) cptr->ptr[PTBL]++; + } + } + if ((songinit == PLAY_STOPPED) || (cptr->tick != cptr->gatetimer)) goto NEXTCHN_S; + + // New notes processing +GETNEWNOTES_S: + { + unsigned char newnote; + + newnote = pattern[cptr->pattnum][cptr->pattptr]; + if (pattern[cptr->pattnum][cptr->pattptr+1]) + cptr->instr = pattern[cptr->pattnum][cptr->pattptr+1]; + cptr->newcommand = pattern[cptr->pattnum][cptr->pattptr+2]; + cptr->newcmddata = pattern[cptr->pattnum][cptr->pattptr+3]; + cptr->pattptr += 4; + if (pattern[cptr->pattnum][cptr->pattptr] == ENDPATT) + cptr->pattptr = 0x7fffffff; + + if (newnote == KEYOFF) + cptr->gate = 0xfe; + if (newnote == KEYON) + cptr->gate = 0xff; + if (newnote <= LASTNOTE) + { + cptr->newnote = newnote+cptr->trans; + if ((cptr->newcommand) != CMD_TONEPORTA) + { + if (!(instr[cptr->instr].gatetimer & 0x40)) + { + cptr->gate = 0xfe; + if (!(instr[cptr->instr].gatetimer & 0x80)) + { + if (c < 3) + { + sidreg[0x5+7*c] = adparam>>8; + sidreg[0x6+7*c] = adparam&0xff; + } + else + { + sidreg2[0x5+7*(c-3)] = adparam>>8; + sidreg2[0x6+7*(c-3)] = adparam&0xff; + } + } + } + } + } + } +NEXTCHN_S: + if (cptr->mute) + { + if (c < 3) + sidreg[0x4+7*c] = cptr->wave = 0x08; + else + sidreg2[0x4+7*(c-3)] = cptr->wave = 0x08; + } + else + { + if (c < 3) + { + sidreg[0x0+7*c] = cptr->freq & 0xff; + sidreg[0x1+7*c] = cptr->freq >> 8; + sidreg[0x2+7*c] = cptr->pulse & 0xfe; + sidreg[0x3+7*c] = cptr->pulse >> 8; + sidreg[0x4+7*c] = cptr->wave & cptr->gate; + } + else + { + sidreg2[0x0+7*(c-3)] = cptr->freq & 0xff; + sidreg2[0x1+7*(c-3)] = cptr->freq >> 8; + sidreg2[0x2+7*(c-3)] = cptr->pulse & 0xfe; + sidreg2[0x3+7*(c-3)] = cptr->pulse >> 8; + sidreg2[0x4+7*(c-3)] = cptr->wave & cptr->gate; + } + } + cptr++; + } + } + if (songinit != PLAY_STOPPED) incrementtime(); +} + +void sequencer_stereo(int c, CHN *cptr) +{ + if ((songinit != PLAY_STOPPED) && (cptr->pattptr == 0x7fffffff)) + { + cptr->pattptr = startpattpos * 4; + if (!cptr->advance) goto SEQDONE_S; + // Song loop + if (songorder_stereo[psnum][c][cptr->songptr] == LOOPSONG) + { + cptr->songptr = songorder_stereo[psnum][c][cptr->songptr+1]; + if (cptr->songptr >= songlen_stereo[psnum][c]) + { + stopsong(); + cptr->songptr = 0; + goto SEQDONE_S; + } + } + // Transpose + if ((songorder_stereo[psnum][c][cptr->songptr] >= TRANSDOWN) && (songorder_stereo[psnum][c][cptr->songptr] < LOOPSONG)) + { + cptr->trans = songorder_stereo[psnum][c][cptr->songptr]-TRANSUP; + cptr->songptr++; + } + // Repeat + if ((songorder_stereo[psnum][c][cptr->songptr] >= REPEAT) && (songorder_stereo[psnum][c][cptr->songptr] < TRANSDOWN)) + { + cptr->repeat = songorder_stereo[psnum][c][cptr->songptr]-REPEAT; + cptr->songptr++; + } + // Pattern number + cptr->pattnum = songorder_stereo[psnum][c][cptr->songptr]; + if (cptr->repeat) + cptr->repeat--; + else + cptr->songptr++; + + // Check for illegal pattern now + if (cptr->pattnum >= MAX_PATT) + { + stopsong(); + cptr->pattnum = 0; + } + if (cptr->pattptr >= (pattlen[cptr->pattnum] * 4)) + cptr->pattptr = 0; + + // Check for playback endpos + if ((lastsonginit != PLAY_BEGINNING) && (esend[c] > 0) && (esend[c] > espos[c]) && (cptr->songptr > esend[c]) && (espos[c] < songlen_stereo[psnum][c])) + cptr->songptr = espos[c]; + } +SEQDONE_S: + {} +} diff --git a/src/gplay.h b/src/gplay.h index 5e6500b..de92e68 100644 --- a/src/gplay.h +++ b/src/gplay.h @@ -57,5 +57,6 @@ void releasenote(int chnnum); void mutechannel(int chnnum); int isplaying(void); void playroutine(void); +void playroutine_stereo(void); #endif diff --git a/src/greloc.c b/src/greloc.c index f2b9c18..4b6822a 100644 --- a/src/greloc.c +++ b/src/greloc.c @@ -1,5 +1,5 @@ // -// GOATTRACKER v2 packer/relocator +// LoadTracker packer/relocator // #define GRELOC_C @@ -86,27 +86,11 @@ int nozerospeed; struct membuf src = STATIC_MEMBUF_INIT; struct membuf dest = STATIC_MEMBUF_INIT; -#ifdef GT2RELOC -#ifdef __WIN32__ -extern FILE *STDOUT, *STDERR; -#else -#define STDOUT stdout -#define STDERR stderr -#endif -extern char packedsongname[MAX_PATHNAME]; -#define clearscreen() -#define fliptoscreen() -#define waitkeynoupdate() -#define printtextc(x, y, b) fputs(b, STDERR) -#define printmainscreen() -#endif - void relocator(void) { -#ifndef GT2RELOC char packedsongname[MAX_FILENAME]; char packedfilter[MAX_FILENAME]; -#endif + unsigned char *packeddata = NULL; char *playername = "player.s"; @@ -205,8 +189,7 @@ void relocator(void) membuf_free(&src); membuf_free(&dest); - int maxChns = MAX_CHN; - if (numsids == 1) maxChns = 3; + int maxChns = 3; // Process song-orderlists countpatternlengths(); @@ -523,7 +506,6 @@ void relocator(void) findtableduplicates(c); // Select playroutine options -#ifndef GT2RELOC clearscreen(); printblankc(0, 0, colors.CHEADER, MAX_COLUMNS); if (!strlen(loadedsongfilename)) @@ -572,7 +554,7 @@ void relocator(void) { playerversion &= ~PLAYER_SOUNDEFFECTS; playerversion &= ~PLAYER_ZPGHOSTREGS; - playerversion &= ~PLAYER_FULLBUFFERED; + playerversion &= ~PLAYER_FULLBUFFERED; } } break; @@ -597,7 +579,7 @@ void relocator(void) } } if (selectdone == -1) goto PRCLEANUP; -#endif + // Disable optimizations if necessary if (playerversion & PLAYER_NOOPTIMIZATION) { @@ -945,10 +927,6 @@ void relocator(void) if (nopulse) pulsetblsize = 0; if (nofilter) filttblsize = 0; -#ifdef GT2RELOC - fprintf(STDOUT, "Player address: $%04X\n", playeradr); - fprintf(STDOUT, "Zeropage address: $%04X\n", zeropageadr); -#else sprintf(textbuffer, "SELECT START ADDRESS: (CURSORS=MOVE, ENTER=ACCEPT, ESC=CANCEL)"); printtext(1, 11, 15, textbuffer); @@ -1074,7 +1052,7 @@ void relocator(void) } if (selectdone == -1) goto PRCLEANUP; -#endif + // Validate frequencytable parameters if (lastnote < firstnote) lastnote = firstnote; @@ -1430,25 +1408,6 @@ void relocator(void) } // Print results -#ifdef GT2RELOC - fprintf(STDOUT, "packing results:\n"); - fprintf(STDOUT, "Playroutine: %d bytes\n", playersize); - fprintf(STDOUT, "Songtable: %d bytes\n", songtblsize); - fprintf(STDOUT, "Song-orderlists: %d bytes\n", songdatasize); - fprintf(STDOUT, "Patterntable: %d bytes\n", patttblsize); - fprintf(STDOUT, "Patterns: %d bytes\n", pattdatasize); - fprintf(STDOUT, "Instruments: %d bytes\n", instrsize); - fprintf(STDOUT, "Tables: %d bytes\n", wavetblsize+pulsetblsize+filttblsize+speedtblsize); - fprintf(STDOUT, "Total size: %d bytes\n", packedsize); - - songhandle = fopen(packedsongname, "wb"); - if (!songhandle) - { - fprintf(STDERR, "error: could not open output file '%s'.\n", packedsongname); - goto PRCLEANUP; - } - -#else clearscreen(); printblankc(0, 0, colors.CHEADER, MAX_COLUMNS); if (!strlen(loadedsongfilename)) @@ -1594,7 +1553,6 @@ void relocator(void) } songhandle = fopen(packedsongname, "wb"); } -#endif if (fileformat == FORMAT_PRG) { @@ -2196,3 +2154,1567 @@ void calcspeedtest(unsigned char pos) } +void relocator_stereo(void) +{ + char packedsongname[MAX_FILENAME]; + char packedfilter[MAX_FILENAME]; + unsigned char *packeddata = NULL; + char *playername = "player_s.s"; + + int tableerrortype = TYPE_NONE; + int tableerrorcause = CAUSE_NONE; + int tableerrorsource1 = 0; + int tableerrorsource2 = 0; + int patterns = 0; + int songs = 0; + int instruments = 0; + int numlegato = 0; + int numnohr = 0; + int numnormal = 0; + int freenormal; + int freenohr; + int freelegato; + int transuprange = 0; + int transdownrange = 0; + int pattdatasize = 0; + int patttblsize = 0; + int songdatasize = 0; + int songtblsize = 0; + int instrsize = 0; + int wavetblsize = 0; + int pulsetblsize = 0; + int filttblsize = 0; + int speedtblsize = 0; + int playersize = 0; + int packedsize = 0; + FILE *songhandle = NULL; + int selectdone; + int opt = 0; + unsigned char speedcode[] = {0xa2,0x00,0x8e,0x04,0xdc,0xa2,0x00,0x8e,0x05,0xdc}; + int c,d,e; + unsigned char patttemp[512]; + unsigned char *songwork = NULL; + unsigned char *pattwork = NULL; + unsigned char *instrwork = NULL; + + channels = 6; + fixedparams = 1; + simplepulse = 1; + firstnote = MAX_NOTES-1; + lastnote = 0; + patternlastnote = 0; + noeffects = 1; + nogate = 1; + nofilter = 1; + nofiltermod = 1; + nopulse = 1; + nopulsemod = 1; + nowavedelay = 1; + nowavecmd = 1; + norepeat = 1; + notrans = 1; + noportamento = 1; + notoneporta = 1; + novib = 1; + noinsvib = 1; + nosetad = 1; + nosetsr = 1; + nosetwave = 1; + nosetwaveptr = 1; + nosetpulseptr = 1; + nosetfiltptr = 1; + nosetfiltcutoff = 1; + nosetfiltctrl = 1; + nosetmastervol = 1; + nofunktempo = 1; + noglobaltempo = 1; + nochanneltempo = 1; + nofirstwavecmd = 1; + nocalculatedspeed = 1; + nonormalspeed = 1; + nozerospeed = 1; + + stopsong(); + + memset(pattused, 0, sizeof pattused); + memset(instrused, 0, sizeof instrused); + memset(chnused, 0, sizeof chnused); + memset(tableused, 0, sizeof tableused); + memset(tablemap, 0, sizeof tablemap); + tableerror = 0; + + membuf_free(&src); + membuf_free(&dest); + + // Process song-orderlists + countpatternlengths(); + // Calculate amount of songs with nonzero length + for (c = 0; c < MAX_SONGS; c++) + { + if ((songlen_stereo[c][0]) && + (songlen_stereo[c][1]) && + (songlen_stereo[c][2])) + { + // See which patterns are used in this song + for (d = 0; d < MAX_CHN; d++) + { + songdatasize += songlen_stereo[c][d]+2; + for (e = 0; e < songlen_stereo[c][d]; e++) + { + if (songorder_stereo[c][d][e] < REPEAT) + { + int f; + int num = songorder_stereo[c][d][e]; + + pattused[num] = 1; + for (f = 0; f < pattlen[num]; f++) + { + if ((pattern[num][f*4] != REST) || (pattern[num][f*4+1]) || (pattern[num][f*4+2])) + chnused[d] = 1; + } + } + else + { + if (songorder_stereo[c][d][e] >= TRANSDOWN) + { + notrans = 0; + if (songorder_stereo[c][d][e] < TRANSUP) + { + int newtransdownrange = -(songorder_stereo[c][d][e] - TRANSUP); + if (newtransdownrange > transdownrange) transdownrange = newtransdownrange; + } + else + { + int newtransuprange = songorder_stereo[c][d][e] - TRANSUP; + if (newtransuprange > transuprange) transuprange = newtransuprange; + } + } + else norepeat = 0; + } + } + if (songorder_stereo[c][d][songlen_stereo[c][d]+1] >= songlen_stereo[c][d]) + { + sprintf(textbuffer, "ILLEGAL SONG RESTART POSITION! (SUBTUNE %02X, CHANNEL %d)", c, d+1); + clearscreen(); + printtextc(MAX_ROWS/2, 15, textbuffer); + fliptoscreen(); + waitkeynoupdate(); + goto PRCLEANUP_S; + } + } + songs++; + } + } + + if (!songs) + { + clearscreen(); + printtextc(MAX_ROWS/2, colors.CTITLE, "NO SONGS, NO DATA TO SAVE!"); + fliptoscreen(); + waitkeynoupdate(); + goto PRCLEANUP_S; + } + + // Build the pattern-mapping + // Instrument 1 is always used + instrused[1] = 1; + for (c = 0; c < MAX_PATT; c++) + { + if (pattused[c]) + { + pattmap[c] = patterns; + patterns++; + + // See which instruments/tablecommands are used + for (d = 0; d < pattlen[c]; d++) + { + tableerror = 0; + + if ((pattern[c][d*4] == KEYOFF) || (pattern[c][d*4] == KEYON)) + nogate = 0; + if (pattern[c][d*4+1]) + instrused[pattern[c][d*4+1]] = 1; + if (pattern[c][d*4+2]) + noeffects = 0; + if ((pattern[c][d*4+2] >= CMD_SETWAVEPTR) && (pattern[c][d*4+2] <= CMD_SETFILTERPTR)) + exectable(pattern[c][d*4+2] - CMD_SETWAVEPTR, pattern[c][d*4+3]); + if ((pattern[c][d*4+2] >= CMD_PORTAUP) && (pattern[c][d*4+2] <= CMD_VIBRATO)) + { + exectable(STBL, pattern[c][d*4+3]); + calcspeedtest(pattern[c][d*4+3]); + } + if (pattern[c][d*4+2] == CMD_FUNKTEMPO) + exectable(STBL, pattern[c][d*4+3]); + if (pattern[c][d*4+2] == CMD_FUNKTEMPO) + { + nofunktempo = 0; + noglobaltempo = 0; + } + if ((pattern[c][d*4+2] == CMD_SETTEMPO) && ((pattern[c][d*4+3] & 0x7f) < 3)) nofunktempo = 0; + + // See, which are the highest/lowest notes used + if ((pattern[c][d*4] >= FIRSTNOTE) && (pattern[c][d*4] <= LASTNOTE)) + { + int newfirstnote = pattern[c][d*4] - FIRSTNOTE - transdownrange; + int newlastnote = pattern[c][d*4] - FIRSTNOTE + transuprange; + if (newfirstnote < 0) newfirstnote = 0; + if (newlastnote > MAX_NOTES-1) newlastnote = MAX_NOTES-1; + + if (newfirstnote < firstnote) firstnote = newfirstnote; + if (newlastnote > lastnote) + { + patternlastnote = newlastnote; + lastnote = newlastnote; + } + if (newfirstnote > lastnote) + { + patternlastnote = newfirstnote; + lastnote = newfirstnote; + } + } + if ((tableerror) && (!tableerrortype)) + { + tableerrortype = tableerror; + tableerrorcause = CAUSE_PATTERN; + tableerrorsource1 = c; + tableerrorsource2 = d; + } + } + } + } + + // Count amount of normal, nohr, and legato instruments + // Also see if special first wave parameters are used + for (c = 0; c < MAX_INSTR; c++) + { + if (instrused[c]) + { + if (instr[c].gatetimer & 0x40) numlegato++; + else + { + if (instr[c].gatetimer & 0x80) numnohr++; + else numnormal++; + } + if ((!instr[c].firstwave) || (instr[c].firstwave >= 0xfe)) + nofirstwavecmd = 0; + } + } + freenormal = 1; + freenohr = freenormal + numnormal; + freelegato = freenohr + numnohr; + + // Build the instrument-mapping + for (c = 0; c < MAX_INSTR; c++) + { + if (instrused[c]) + { + if (instr[c].gatetimer & 0x40) instrmap[c] = freelegato++; + else + { + if (instr[c].gatetimer & 0x80) instrmap[c] = freenohr++; + else instrmap[c] = freenormal++; + } + instruments++; + for (d = 0; d < MAX_TABLES; d++) + { + tableerror = 0; + exectable(d, instr[c].ptr[d]); + if (d == STBL) calcspeedtest(instr[c].ptr[d]); + if ((tableerror) && (!tableerrortype)) + { + tableerrortype = tableerror; + tableerrorcause = CAUSE_INSTRUMENT; + tableerrorsource1 = c; + tableerrorsource2 = d; + } + } + } + } + + // Execute tableprograms invoked from wavetable commands + for (c = 0; c < MAX_TABLELEN; c++) + { + if (tableused[WTBL][c+1]) + { + if ((ltable[WTBL][c] >= WAVECMD) && (ltable[WTBL][c] <= WAVELASTCMD)) + { + d = -1; + tableerror = 0; + + switch(ltable[WTBL][c] - WAVECMD) + { + case CMD_PORTAUP: + case CMD_PORTADOWN: + case CMD_TONEPORTA: + case CMD_VIBRATO: + d = STBL; + calcspeedtest(rtable[WTBL][c]); + break; + + case CMD_SETPULSEPTR: + d = PTBL; + nopulse = 0; + break; + + case CMD_SETFILTERPTR: + d = FTBL; + nofilter = 0; + break; + + case CMD_DONOTHING: + case CMD_SETWAVEPTR: + case CMD_FUNKTEMPO: + sprintf(textbuffer, "ILLEGAL WAVETABLE COMMAND (ROW %02X, COMMAND %X)", c+1, ltable[WTBL][c] - WAVECMD); + clearscreen(); + printtextc(MAX_ROWS/2, 15, textbuffer); + fliptoscreen(); + waitkeynoupdate(); + goto PRCLEANUP_S; + } + + if (d != -1) exectable(d, rtable[WTBL][c]); + + if ((tableerror) && (!tableerrortype)) + { + tableerrortype = tableerror; + tableerrorcause = CAUSE_WAVECMD; + tableerrorsource1 = c+1; + tableerrorsource2 = d; + } + } + } + } + + // Build the table-mapping + for (c = 0; c < MAX_TABLES; c++) + { + int e = 1; + for (d = 0; d < MAX_TABLELEN; d++) + { + if (tableused[c][d+1]) + { + tablemap[c][d+1] = e; + e++; + } + } + } + + // Check for table errors + if (tableerrorcause) + { + clearscreen(); + switch(tableerrortype) + { + case TYPE_JUMP: + sprintf(textbuffer, "TABLE POINTER POINTS TO A JUMP! "); + break; + + case TYPE_OVERFLOW: + sprintf(textbuffer, "TABLE EXECUTION OVERFLOWS! "); + break; + } + switch (tableerrorcause) + { + case CAUSE_PATTERN: + sprintf(textbuffer + strlen(textbuffer), "(PATTERN %02X, ROW %02d)", tableerrorsource1, tableerrorsource2); + break; + + case CAUSE_WAVECMD: + sprintf(textbuffer + strlen(textbuffer), "WAVETABLE CMD (ROW %02X, ", tableerrorsource1); + goto TABLETYPE_S; + + case CAUSE_INSTRUMENT: + sprintf(textbuffer + strlen(textbuffer), "(INSTRUMENT %02X, ", tableerrorsource1); +TABLETYPE_S: + switch (tableerrorsource2) + { + case WTBL: + strcat(textbuffer, "WAVE"); + break; + + case PTBL: + strcat(textbuffer, "PULSE"); + break; + + case FTBL: + strcat(textbuffer, "FILTER"); + break; + } + strcat(textbuffer, ")"); + break; + } + printtextc(MAX_ROWS/2, 15, textbuffer); + + fliptoscreen(); + waitkeynoupdate(); + goto PRCLEANUP_S; + } + + // Find duplicate ranges in tables + for (c = 0; c < MAX_TABLES; c++) + findtableduplicates(c); + + // Select playroutine options + clearscreen(); + printblankc(0, 0, colors.CHEADER, MAX_COLUMNS); + if (!strlen(loadedsongfilename)) + sprintf(textbuffer, "%s Packer/Relocator", programname); + else + sprintf(textbuffer, "%s Packer/Relocator - %s", programname, loadedsongfilename); + textbuffer[MAX_COLUMNS] = 0; + printtext(0, 0, colors.CHEADER, textbuffer); + printtext(1, 2, colors.CTITLE, "SELECT PLAYROUTINE OPTIONS: (CURSORS=MOVE/CHANGE, ENTER=ACCEPT, ESC=CANCEL)"); + + playerversion |= PLAYER_BUFFERED; + playerversion &= ~PLAYER_ZPGHOSTREGS; + + selectdone = 0; + while (!selectdone) + { + for (c = 0; c < (MAX_OPTIONS-1); c++) + { + int color = colors.CNORMAL; + if (opt == c) color = colors.CEDIT; + + printtext(1, 3+c, color, playeroptname[c]); + if (playerversion & (PLAYER_BUFFERED << c)) + printtext(24, 3+c, color, "Yes"); + else + printtext(24, 3+c, color, "No "); + } + fliptoscreen(); + waitkeynoupdate(); + + if (win_quitted) + { + exitprogram = 1; + goto PRCLEANUP_S; + } + + switch(rawkey) + { + case KEY_LEFT: + case KEY_RIGHT: + case KEY_SPACE: + playerversion ^= (PLAYER_BUFFERED << opt); + if (opt) + { + if ((playerversion & PLAYER_SOUNDEFFECTS) || (playerversion & PLAYER_ZPGHOSTREGS)) + playerversion |= PLAYER_BUFFERED; + } + else + { + if (!(playerversion & PLAYER_BUFFERED)) + { + playerversion &= ~PLAYER_SOUNDEFFECTS; + playerversion &= ~PLAYER_ZPGHOSTREGS; + } + } + break; + + case KEY_UP: + opt--; + if (opt < 0) opt = MAX_OPTIONS-1; + break; + + case KEY_DOWN: + opt++; + if (opt >= MAX_OPTIONS) opt = 0; + break; + + case KEY_ESC: + selectdone = -1; + break; + + case KEY_ENTER: + selectdone = 1; + break; + } + + playerversion |= PLAYER_BUFFERED; + playerversion &= ~PLAYER_ZPGHOSTREGS; + } + if (selectdone == -1) goto PRCLEANUP_S; + + // Disable optimizations if necessary + if (playerversion & PLAYER_NOOPTIMIZATION) + { + fixedparams = 0; + if (!numlegato) numlegato++; + + simplepulse = 0; + firstnote = 0; + lastnote = MAX_NOTES-1; + nogate = 0; + noeffects = 0; + nofilter = 0; + nofiltermod = 0; + nopulse = 0; + nopulsemod = 0; + nowavedelay = 0; + nowavecmd = 0; + norepeat = 0; + notrans = 0; + noportamento = 0; + notoneporta = 0; + novib = 0; + noinsvib = 0; + nosetad = 0; + nosetsr = 0; + nosetwave = 0; + nosetwaveptr = 0; + nosetpulseptr = 0; + nosetfiltptr = 0; + nosetfiltcutoff = 0; + nosetfiltctrl = 0; + nosetmastervol = 0; + nofunktempo = 0; + noglobaltempo = 0; + nochanneltempo = 0; + nofirstwavecmd = 0; + nocalculatedspeed = 0; + nonormalspeed = 0; + nozerospeed = 0; + } + + // Make sure buffering is used if it is needed + if ((playerversion & PLAYER_SOUNDEFFECTS) || (playerversion & PLAYER_ZPGHOSTREGS)) + playerversion |= PLAYER_BUFFERED; + + // Allocate memory for song-orderlists + songtblsize = songs*6; + songwork = malloc(songdatasize); + if (!songwork) + { + clearscreen(); + printtextc(MAX_ROWS/2, colors.CTITLE, "OUT OF MEMORY IN PACKER/RELOCATOR!"); + fliptoscreen(); + waitkeynoupdate(); + goto PRCLEANUP_S; + } + + // Generate songorderlists & songtable + songdatasize = 0; + for (c = 0; c < songs; c++) + { + if ((songlen_stereo[c][0]) && + (songlen_stereo[c][1]) && + (songlen_stereo[c][2])) + { + for (d = 0; d < MAX_CHN; d++) + { + songoffset_stereo[c][d] = songdatasize; + songsize_stereo[c][d] = songlen_stereo[c][d] + 2; + + for (e = 0; e < songlen_stereo[c][d]; e++) + { + // Pattern + if (songorder_stereo[c][d][e] < REPEAT) + songwork[songdatasize++] = pattmap[songorder_stereo[c][d][e]]; + else + { + // Transpose + if (songorder_stereo[c][d][e] >= TRANSDOWN) + { + songwork[songdatasize++] = songorder_stereo[c][d][e]; + } + // Repeat sequence: must be swapped + else + { + // See that repeat amount is more than 1 + if (songorder_stereo[c][d][e] > REPEAT) + { + // Insanity check that a pattern indeed follows + if (songorder_stereo[c][d][e+1] < REPEAT) + { + songwork[songdatasize++] = pattmap[songorder_stereo[c][d][e+1]]; + songwork[songdatasize++] = songorder_stereo[c][d][e]; + e++; + } + else + songwork[songdatasize++] = songorder_stereo[c][d][e]; + } + } + } + } + // Endmark & repeat position + songwork[songdatasize++] = songorder_stereo[c][d][e++]; + songwork[songdatasize++] = songorder_stereo[c][d][e++]; + } + } + else + { + for (d = 0; d < MAX_CHN; d++) + { + songoffset_stereo[c][d] = songdatasize; + songsize_stereo[c][d] = 0; + } + } + } + + // Calculate total size of patterns + for (c = 0; c < MAX_PATT; c++) + { + if (pattused[c]) + { + int result = packpattern(patttemp, pattern[c], pattlen[c]); + + if (result < 0) + { + clearscreen(); + sprintf(textbuffer, "PATTERN %02X IS TOO COMPLEX (OVER 256 BYTES PACKED)!", c); + printtextc(MAX_ROWS/2, 15, textbuffer); + fliptoscreen(); + waitkeynoupdate(); + goto PRCLEANUP_S; + } + pattdatasize += result; + } + } + + patttblsize = patterns*2; + pattwork = malloc(pattdatasize); + if (!pattwork) + { + clearscreen(); + printtextc(MAX_ROWS/2, colors.CTITLE, "OUT OF MEMORY IN PACKER/RELOCATOR!"); + fliptoscreen(); + waitkeynoupdate(); + goto PRCLEANUP_S; + } + + // This time pack the patterns for real + pattdatasize = 0; + d = 0; + for (c = 0; c < MAX_PATT; c++) + { + if (pattused[c]) + { + pattoffset[d] = pattdatasize; + pattsize[d] = packpattern(&pattwork[pattdatasize], pattern[c], pattlen[c]); + pattdatasize += pattsize[d]; + d++; + } + } + + // Then process instruments + instrsize = instruments*9; + instrwork = malloc(instrsize); + if (!instrwork) + { + clearscreen(); + printtextc(MAX_ROWS/2, colors.CTITLE, "OUT OF MEMORY IN PACKER/RELOCATOR!"); + fliptoscreen(); + waitkeynoupdate(); + goto PRCLEANUP_S; + } + + for (c = 1; c < MAX_INSTR; c++) + { + if (instrused[c]) + { + d = instrmap[c] - 1; + instrwork[d] = instr[c].ad; + instrwork[d+instruments] = instr[c].sr; + instrwork[d+instruments*2] = tablemap[WTBL][instr[c].ptr[WTBL]]; + instrwork[d+instruments*3] = tablemap[PTBL][instr[c].ptr[PTBL]]; + instrwork[d+instruments*4] = tablemap[FTBL][instr[c].ptr[FTBL]]; + if (instr[c].vibdelay) + { + instrwork[d+instruments*5] = tablemap[STBL][instr[c].ptr[STBL]]; + instrwork[d+instruments*6] = instr[c].vibdelay - 1; + } + else + { + instrwork[d+instruments*5] = 0; + instrwork[d+instruments*6] = 0; + } + instrwork[d+instruments*7] = instr[c].gatetimer & 0x3f; + instrwork[d+instruments*8] = instr[c].firstwave; + + if (instr[c].ptr[STBL]) + { + novib = 0; + noinsvib = 0; + } + if (instr[c].ptr[PTBL]) + nopulse = 0; + if (instr[c].ptr[FTBL]) + nofilter = 0; + + // See if all instruments use same gatetimer & firstwave parameters + if ((instr[c].gatetimer != instr[1].gatetimer) || + (instr[c].firstwave != instr[1].firstwave)) + fixedparams = 0; + // or if special firstwave commands are in use + if ((!instr[c].firstwave) || (instr[c].firstwave >= 0xfe)) + fixedparams = 0; + } + } + + // Disable sameparam optimization for multispeed stability + if (multiplier > 1) + { + fixedparams = 0; + numlegato++; + numnohr++; + } + + if (fixedparams) instrsize -= instruments*2; + if (noinsvib) instrsize -= instruments*2; + if (nopulse) instrsize -= instruments; + if (nofilter) instrsize -= instruments; + + // Process tables + for (c = 0; c < MAX_TABLELEN; c++) + { + if (tableused[WTBL][c+1]) + { + wavetblsize += 2; + if ((ltable[WTBL][c] >= WAVEDELAY) && (ltable[WTBL][c] <= WAVELASTDELAY)) nowavedelay = 0; + if ((ltable[WTBL][c] >= WAVECMD) && (ltable[WTBL][c] <= WAVELASTCMD)) + { + nowavecmd = 0; + noeffects = 0; + switch (ltable[WTBL][c] - WAVECMD) + { + case CMD_PORTAUP: + case CMD_PORTADOWN: + noportamento = 0; + break; + + case CMD_TONEPORTA: + notoneporta = 0; + break; + + case CMD_VIBRATO: + novib = 0; + break; + + case CMD_SETAD: + nosetad = 0; + break; + + case CMD_SETSR: + nosetsr = 0; + break; + + case CMD_SETWAVE: + nosetwave = 0; + break; + + case CMD_SETPULSEPTR: + nosetpulseptr = 0; + break; + + case CMD_SETFILTERPTR: + nosetfiltptr = 0; + break; + + case CMD_SETFILTERCUTOFF: + nosetfiltcutoff = 0; + break; + + case CMD_SETFILTERCTRL: + nosetfiltctrl = 0; + break; + + case CMD_SETMASTERVOL: + nosetmastervol = 0; + break; + } + } + if (ltable[WTBL][c] < WAVECMD) + { + if (rtable[WTBL][c] <= 0x80) + { + int newlastnote = rtable[WTBL][c] + patternlastnote; + if (newlastnote > MAX_NOTES - 1) newlastnote = MAX_NOTES - 1; + if (rtable[WTBL][c] >= 0x20) firstnote = 0; + if (newlastnote > lastnote) lastnote = newlastnote; + } + else + { + int newfirstnote = rtable[WTBL][c] & 0x7f; + int newlastnote = rtable[WTBL][c] & 0x7f; + if (newlastnote > MAX_NOTES - 1) newlastnote = MAX_NOTES - 1; + if (newfirstnote < firstnote) firstnote = newfirstnote; + if (newlastnote > lastnote) lastnote = newlastnote; + } + } + } + } + for (c = 0; c < MAX_TABLELEN; c++) + { + if (tableused[PTBL][c+1]) + { + pulsetblsize += 2; + if ((ltable[PTBL][c] >= 0x80) && (ltable[PTBL][c] != 0xff)) + { + if (rtable[PTBL][c] & 0xf) simplepulse = 0; + } + if (ltable[PTBL][c] < 0x80) + { + nopulsemod = 0; + if (rtable[PTBL][c] & 0xf) simplepulse = 0; + } + } + } + for (c = 0; c < MAX_TABLELEN; c++) + { + if (tableused[FTBL][c+1]) + { + filttblsize += 2; + if (ltable[FTBL][c] < 0x80) nofiltermod = 0; + } + } + for (c = 0; c < MAX_TABLELEN; c++) + { + if (tableused[STBL][c+1]) speedtblsize += 2; + } + // Zero entry of speedtable + if ((!novib) || (!nofunktempo) || (!noportamento) || (!notoneporta)) + speedtblsize += 2; + + if (nopulse) pulsetblsize = 0; + if (nofilter) filttblsize = 0; + + sprintf(textbuffer, "SELECT START ADDRESS: (CURSORS=MOVE, ENTER=ACCEPT, ESC=CANCEL)"); + printtext(1, 10, 15, textbuffer); + + selectdone = 0; + while (!selectdone) + { + sprintf(textbuffer, "$%04X", playeradr); + printtext(1, 11, 10, textbuffer); + + fliptoscreen(); + waitkeynoupdate(); + + if (win_quitted) + { + exitprogram = 1; + goto PRCLEANUP_S; + } + + switch(rawkey) + { + case KEY_LEFT: + playeradr -= 0x0400; + playeradr &= 0xff00; + break; + + case KEY_UP: + playeradr += 0x0100; + playeradr &= 0xff00; + break; + + case KEY_RIGHT: + playeradr += 0x0400; + playeradr &= 0xff00; + break; + + case KEY_DOWN: + playeradr -= 0x0100; + playeradr &= 0xff00; + break; + + case KEY_ESC: + selectdone = -1; + break; + + case KEY_ENTER: + selectdone = 1; + break; + } + } + + if (selectdone == -1) goto PRCLEANUP_S; + + sprintf(textbuffer, "SELECT ZEROPAGE ADDRESS: (CURSORS=MOVE, ENTER=ACCEPT, ESC=CANCEL)"); + printtext(1, 13, 15, textbuffer); + + selectdone = 0; + while (!selectdone) + { + if (playerversion & PLAYER_ZPGHOSTREGS) + { + if (zeropageadr < 0x02) zeropageadr = 0xe5; + if (zeropageadr > 0xe5) zeropageadr = 0x02; + } + else + { + if (zeropageadr < 0x02) zeropageadr = 0xfe; + if (zeropageadr > 0xfe) zeropageadr = 0x02; + } + + if (!(playerversion & PLAYER_ZPGHOSTREGS)) + { + if (zeropageadr < 0x90) + sprintf(textbuffer, "$%02X-$%02X (Used by BASIC interpreter) ", zeropageadr, zeropageadr+1); + if ((zeropageadr >= 0x90) && (zeropageadr < 0xfb)) + sprintf(textbuffer, "$%02X-$%02X (Used by KERNAL routines) ", zeropageadr, zeropageadr+1); + if ((zeropageadr >= 0xfb) && (zeropageadr < 0xfe)) + sprintf(textbuffer, "$%02X-$%02X (Unused) ", zeropageadr, zeropageadr+1); + if (zeropageadr >= 0xfe) + sprintf(textbuffer, "$%02X-$%02X ($FF used by BASIC interpreter)", zeropageadr, zeropageadr+1); + } + else + { + sprintf(textbuffer, "$%02X-$%02X (ghostregs start at %02X)", zeropageadr, zeropageadr+26, zeropageadr); + } + + printtext(1, 14, 10, textbuffer); + + fliptoscreen(); + waitkeynoupdate(); + + if (win_quitted) + { + exitprogram = 1; + goto PRCLEANUP_S; + } + + switch(rawkey) + { + case KEY_LEFT: + zeropageadr -= 0x10; + break; + + case KEY_UP: + zeropageadr++; + break; + + case KEY_RIGHT: + zeropageadr += 0x10; + break; + + case KEY_DOWN: + zeropageadr--; + break; + + case KEY_ESC: + selectdone = -1; + break; + + case KEY_ENTER: + selectdone = 1; + break; + } + } + + if (selectdone == -1) goto PRCLEANUP_S; + + // Validate frequencytable parameters + if (lastnote < firstnote) + lastnote = firstnote; + if (firstnote < 0) firstnote = 0; + if (!nocalculatedspeed) + lastnote++; // Calculated speeds need the next frequency value + if (lastnote > MAX_NOTES-1) lastnote = MAX_NOTES-1; + // For sound effect support, always use the full table + if (playerversion & PLAYER_SOUNDEFFECTS) + { + firstnote = 0; + lastnote = MAX_NOTES-1; + } + + // Insert baseaddresses + insertdefine("base", playeradr); + insertdefine("zpbase", zeropageadr); + insertdefine("SIDBASE", sidaddress); + insertdefine("SID2BASE", sid2address); + + // Insert conditionals + insertdefine("SOUNDSUPPORT", (playerversion & PLAYER_SOUNDEFFECTS) ? 1 : 0); + insertdefine("VOLSUPPORT", (playerversion & PLAYER_VOLUME) ? 1 : 0); + insertdefine("BUFFEREDWRITES", (playerversion & PLAYER_BUFFERED) ? 1 : 0); + insertdefine("ZPGHOSTREGS", (playerversion & PLAYER_ZPGHOSTREGS) ? 1 : 0); + insertdefine("FIXEDPARAMS", fixedparams); + insertdefine("SIMPLEPULSE", simplepulse); + insertdefine("PULSEOPTIMIZATION", optimizepulse); + insertdefine("REALTIMEOPTIMIZATION", optimizerealtime); + insertdefine("NOAUTHORINFO", (playerversion & PLAYER_AUTHORINFO) ? 0 : 1); + insertdefine("NOEFFECTS", noeffects); + insertdefine("NOGATE", nogate); + insertdefine("NOFILTER", nofilter); + insertdefine("NOFILTERMOD", nofiltermod); + insertdefine("NOPULSE", nopulse); + insertdefine("NOPULSEMOD", nopulsemod); + insertdefine("NOWAVEDELAY", nowavedelay); + insertdefine("NOWAVECMD", nowavecmd); + insertdefine("NOREPEAT", norepeat); + insertdefine("NOTRANS", notrans); + insertdefine("NOPORTAMENTO", noportamento); + insertdefine("NOTONEPORTA", notoneporta); + insertdefine("NOVIB", novib); + insertdefine("NOINSTRVIB", noinsvib); + insertdefine("NOSETAD", nosetad); + insertdefine("NOSETSR", nosetsr); + insertdefine("NOSETWAVE", nosetwave); + insertdefine("NOSETWAVEPTR", nosetwaveptr); + insertdefine("NOSETPULSEPTR", nosetpulseptr); + insertdefine("NOSETFILTPTR", nosetfiltptr); + insertdefine("NOSETFILTCTRL", nosetfiltctrl); + insertdefine("NOSETFILTCUTOFF", nosetfiltcutoff); + insertdefine("NOSETMASTERVOL", nosetmastervol); + insertdefine("NOFUNKTEMPO", nofunktempo); + insertdefine("NOGLOBALTEMPO", noglobaltempo); + insertdefine("NOCHANNELTEMPO", nochanneltempo); + insertdefine("NOFIRSTWAVECMD", nofirstwavecmd); + insertdefine("NOCALCULATEDSPEED", nocalculatedspeed); + insertdefine("NONORMALSPEED", nonormalspeed); + insertdefine("NOZEROSPEED", nozerospeed); + + // Insert parameters + insertdefine("NUMCHANNELS", channels); + insertdefine("NUMSONGS", songs); + insertdefine("FIRSTNOTE", firstnote); + insertdefine("FIRSTNOHRINSTR", numnormal + 1); + insertdefine("FIRSTLEGATOINSTR", numnormal + numnohr + 1); + insertdefine("NUMHRINSTR", numnormal); + insertdefine("NUMNOHRINSTR", numnohr); + insertdefine("NUMLEGATOINSTR", numlegato); + insertdefine("ADPARAM", adparam >> 8); + insertdefine("SRPARAM", adparam & 0xff); + if ((instr[MAX_INSTR-1].ad >= 2) && (!(instr[MAX_INSTR-1].ptr[WTBL]))) + insertdefine("DEFAULTTEMPO", instr[MAX_INSTR-1].ad - 1); + else + insertdefine("DEFAULTTEMPO", multiplier ? (multiplier*6-1) : 5); + + // Fixed firstwave & gatetimer + if (fixedparams) + { + insertdefine("FIRSTWAVEPARAM", instr[1].firstwave); + insertdefine("GATETIMERPARAM", instr[1].gatetimer & 0x3f); + } + + // Insert source code of player + if (adparam >= 0xf000) + playername = "altplayer_s.s"; + + if (!insertfile(playername)) + { + clearscreen(); + printtextc(MAX_ROWS/2, colors.CTITLE, "COULD NOT OPEN PLAYROUTINE!"); + fliptoscreen(); + waitkeynoupdate(); + goto PRCLEANUP_S; + } + + // Insert frequencytable + insertlabel("mt_freqtbllo"); + insertbytes(&freqtbllo[firstnote], lastnote-firstnote+1); + insertlabel("mt_freqtblhi"); + insertbytes(&freqtblhi[firstnote], lastnote-firstnote+1); + + // Insert songtable + insertlabel("mt_songtbllo"); + for (c = 0; c < songs*6; c++) + { + sprintf(textbuffer, "mt_song%d", c); + insertaddrlo(textbuffer); + } + insertlabel("mt_songtblhi"); + for (c = 0; c < songs*6; c++) + { + sprintf(textbuffer, "mt_song%d", c); + insertaddrhi(textbuffer); + } + + // Insert patterntable + insertlabel("mt_patttbllo"); + for (c = 0; c < patterns; c++) + { + sprintf(textbuffer, "mt_patt%d", c); + insertaddrlo(textbuffer); + } + insertlabel("mt_patttblhi"); + for (c = 0; c < patterns; c++) + { + sprintf(textbuffer, "mt_patt%d", c); + insertaddrhi(textbuffer); + } + + // Insert instruments + insertlabel("mt_insad"); + insertbytes(&instrwork[0], instruments); + insertlabel("mt_inssr"); + insertbytes(&instrwork[instruments], instruments); + insertlabel("mt_inswaveptr"); + insertbytes(&instrwork[instruments*2], instruments); + if (!nopulse) + { + insertlabel("mt_inspulseptr"); + insertbytes(&instrwork[instruments*3], instruments); + } + if (!nofilter) + { + insertlabel("mt_insfiltptr"); + insertbytes(&instrwork[instruments*4], instruments); + } + if (!noinsvib) + { + insertlabel("mt_insvibparam"); + insertbytes(&instrwork[instruments*5], instruments); + insertlabel("mt_insvibdelay"); + insertbytes(&instrwork[instruments*6], instruments); + } + if (!fixedparams) + { + insertlabel("mt_insgatetimer"); + insertbytes(&instrwork[instruments*7], instruments); + insertlabel("mt_insfirstwave"); + insertbytes(&instrwork[instruments*8], instruments); + } + + // Insert tables + for (c = 0; c < MAX_TABLES; c++) + { + if ((c == PTBL) && (nopulse)) goto SKIPTABLE_S; + if ((c == FTBL) && (nofilter)) goto SKIPTABLE_S; + + // Write table left side + // Extra zero for speedtable + if ((c == STBL) && ((!novib) || (!nofunktempo) || (!noportamento) || (!notoneporta))) insertbyte(0); + // Table label + insertlabel(tableleftname[c]); + + // Table data + for (d = 0; d < MAX_TABLELEN; d++) + { + if (tableused[c][d+1]) + { + switch (c) + { + // In wavetable, convert waveform values for the playroutine + case WTBL: + { + unsigned char wave = ltable[c][d]; + if ((ltable[c][d] >= WAVESILENT) && (ltable[c][d] <= WAVELASTSILENT)) wave &= 0xf; + if ((ltable[c][d] > WAVELASTDELAY) && (ltable[c][d] <= WAVELASTSILENT) && (!nowavedelay)) wave += 0x10; + insertbyte(wave); + } + break; + + case PTBL: + if ((simplepulse) && (ltable[c][d] != 0xff) && (ltable[c][d] > 0x80)) + insertbyte(0x80); + else + insertbyte(ltable[c][d]); + break; + + // In filtertable, modify passband bits + case FTBL: + if ((ltable[c][d] != 0xff) && (ltable[c][d] > 0x80)) + insertbyte(((ltable[c][d] & 0x70) >> 1) | 0x80); + else + insertbyte(ltable[c][d]); + break; + + default: + insertbyte(ltable[c][d]); + break; + } + } + } + + // Write table right side, remapping jumps as necessary + // Extra zero for speedtable + if ((c == STBL) && ((!novib) || (!nofunktempo) || (!noportamento) || (!notoneporta))) insertbyte(0); + // Table label + insertlabel(tablerightname[c]); + + for (d = 0; d < MAX_TABLELEN; d++) + { + if (tableused[c][d+1]) + { + if ((ltable[c][d] != 0xff) || (c == STBL)) + { + switch(c) + { + case WTBL: + if ((ltable[c][d] >= WAVECMD) && (ltable[c][d] <= WAVELASTCMD)) + { + // Remap table-referencing commands + switch (ltable[c][d] - WAVECMD) + { + case CMD_PORTAUP: + case CMD_PORTADOWN: + case CMD_TONEPORTA: + case CMD_VIBRATO: + insertbyte(tablemap[STBL][rtable[c][d]]); + break; + + case CMD_SETPULSEPTR: + insertbyte(tablemap[PTBL][rtable[c][d]]); + break; + + case CMD_SETFILTERPTR: + insertbyte(tablemap[FTBL][rtable[c][d]]); + break; + + default: + insertbyte(rtable[c][d]); + break; + } + } + else + { + // For normal notes, reverse all right side high bits + insertbyte(rtable[c][d] ^ 0x80); + } + break; + + case PTBL: + if (simplepulse) + { + if (ltable[c][d] >= 0x80) + insertbyte((ltable[c][d] & 0x0f) | (rtable[c][d] & 0xf0)); + else + { + int pulsespeed = rtable[c][d] >> 4; + if (rtable[c][d] & 0x80) + { + pulsespeed |= 0xf0; + pulsespeed--; + } + pulsespeed = swapnybbles(pulsespeed); + insertbyte(pulsespeed); + } + } + else + insertbyte(rtable[c][d]); + break; + + default: + insertbyte(rtable[c][d]); + break; + } + } + else + insertbyte(tablemap[c][rtable[c][d]]); + } + } + +SKIPTABLE_S: + ; + } + + // Insert orderlists + for (c = 0; c < songs; c++) + { + for (d = 0; d < MAX_CHN; d++) + { + sprintf(textbuffer, "mt_song%d", c*6+d); + insertlabel(textbuffer); + insertbytes(&songwork[songoffset_stereo[c][d]], songsize_stereo[c][d]); + } + } + + // Insert patterns + for (c = 0; c < patterns; c++) + { + sprintf(textbuffer, "mt_patt%d", c); + insertlabel(textbuffer); + insertbytes(&pattwork[pattoffset[c]], pattsize[c]); + } + + //{ + // FILE *handle = fopen("debug.s", "wb"); + // fwrite(membuf_get(&src), membuf_memlen(&src), 1, handle); + // fclose(handle); + //} + + // Assemble; on error fail in a rude way (the parser does so too) + if (assemble(&src, &dest)) exit(1); + + packeddata = membuf_get(&dest); + packedsize = membuf_memlen(&dest); + playersize = packedsize - songtblsize - songdatasize - patttblsize - pattdatasize - instrsize - wavetblsize - pulsetblsize - filttblsize - speedtblsize; + + // Copy author info + if (playerversion & PLAYER_AUTHORINFO) + { + for (c = 0; c < 32; c++) + { + packeddata[32+c] = authorname[c]; + // Convert 0 to space + if (packeddata[32+c] == 0) packeddata[32+c] = 0x20; + } + } + + // Print results + clearscreen(); + printblankc(0, 0, colors.CHEADER, MAX_COLUMNS); + if (!strlen(loadedsongfilename)) + sprintf(textbuffer, "%s Packer/Relocator", programname); + else + sprintf(textbuffer, "%s Packer/Relocator - %s", programname, loadedsongfilename); + textbuffer[80] = 0; + printtext(0, 0, colors.CHEADER, textbuffer); + + sprintf(textbuffer, "PACKING RESULTS:"); + printtext(1, 2, 15, textbuffer); + + sprintf(textbuffer, "Playroutine: %d bytes", playersize); + printtext(1, 3, 7, textbuffer); + sprintf(textbuffer, "Songtable: %d bytes", songtblsize); + printtext(1, 4, 7, textbuffer); + sprintf(textbuffer, "Song-orderlists: %d bytes", songdatasize); + printtext(1, 5, 7, textbuffer); + sprintf(textbuffer, "Patterntable: %d bytes", patttblsize); + printtext(1, 6, 7, textbuffer); + sprintf(textbuffer, "Patterns: %d bytes", pattdatasize); + printtext(1, 7, 7, textbuffer); + sprintf(textbuffer, "Instruments: %d bytes", instrsize); + printtext(1, 8, 7, textbuffer); + sprintf(textbuffer, "Tables: %d bytes", wavetblsize+pulsetblsize+filttblsize+speedtblsize); + printtext(1, 9, 7, textbuffer); + sprintf(textbuffer, "Total size: %d bytes", packedsize); + printtext(1, 11, 7, textbuffer); + fliptoscreen(); + + + // Now ask for fileformat + printtext(1, 13, colors.CTITLE, "SELECT FORMAT TO SAVE IN: (CURSORS=MOVE, ENTER=ACCEPT, ESC=CANCEL)"); + + selectdone = 0; + + while (!selectdone) + { + switch(fileformat) + { + case FORMAT_SID: + printtext(1, 14, colors.CEDIT, "SID - SIDPlay music file format "); + strcpy(packedfilter, "*.sid"); + break; + + case FORMAT_PRG: + printtext(1, 14, colors.CEDIT, "PRG - C64 native format "); + strcpy(packedfilter, "*.prg"); + break; + + case FORMAT_BIN: + printtext(1, 14, colors.CEDIT, "BIN - Raw binary format (no startaddress)"); + strcpy(packedfilter, "*.bin"); + break; + } + + fliptoscreen(); + waitkeynoupdate(); + + if (win_quitted) + { + exitprogram = 1; + goto PRCLEANUP_S; + } + + switch(rawkey) + { + case KEY_LEFT: + case KEY_DOWN: + fileformat--; + if (fileformat < FORMAT_SID) fileformat = FORMAT_BIN; + break; + + case KEY_RIGHT: + case KEY_UP: + fileformat++; + if (fileformat > FORMAT_BIN) fileformat = FORMAT_SID; + break; + + case KEY_ESC: + selectdone = -1; + break; + + case KEY_ENTER: + selectdone = 1; + break; + } + } + if (selectdone == -1) goto PRCLEANUP_S; + + // By default, copy loaded song name up to the extension + memset(packedsongname, 0, sizeof packedsongname); + for (c = 0; c < strlen(loadedsongfilename); c++) + { + if (loadedsongfilename[c] == '.') break; + packedsongname[c] = loadedsongfilename[c]; + } + switch (fileformat) + { + case FORMAT_PRG: + strcat(packedsongname, ".prg"); + break; + + case FORMAT_BIN: + strcat(packedsongname, ".bin"); + break; + + case FORMAT_SID: + strcat(packedsongname, ".sid"); + break; + } + + // Now ask for filename, retry if unsuccessful + while (!songhandle) + { + if (!fileselector(packedsongname, packedpath, packedfilter, "Save Music+Playroutine", 3)) + goto PRCLEANUP_S; + + if (strlen(packedsongname) < MAX_FILENAME-4) + { + int extfound = 0; + for (c = strlen(packedsongname)-1; c >= 0; c--) + { + if (packedsongname[c] == '.') extfound = 1; + } + if (!extfound) + { + switch (fileformat) + { + case FORMAT_PRG: + strcat(packedsongname, ".prg"); + break; + + case FORMAT_BIN: + strcat(packedsongname, ".bin"); + break; + + case FORMAT_SID: + strcat(packedsongname, ".sid"); + break; + } + } + } + songhandle = fopen(packedsongname, "wb"); + } + + if (fileformat == FORMAT_PRG) + { + fwritele16(songhandle, playeradr); + } + if (fileformat == FORMAT_SID) + { + unsigned char ident[] = {'P', 'S', 'I', 'D', 0x00, 0x03, 0x00, 0x7c}; + unsigned char byte; + // Identification + fwrite(ident, sizeof ident, 1, songhandle); + + // Load address + byte = 0x00; + fwrite8(songhandle, byte); + fwrite8(songhandle, byte); + + // Init address + if ((multiplier > 1) || (!multiplier)) + { + unsigned speedvalue; + byte = (playeradr-10) >> 8; + fwrite8(songhandle, byte); + byte = (playeradr-10) & 0xff; + fwrite8(songhandle, byte); + + if (multiplier) + { + if (ntsc) speedvalue = 0x42c6/multiplier; + else speedvalue = 0x4cc7/multiplier; + } + else + { + if (ntsc) speedvalue = 0x42c6*2; + else speedvalue = 0x4cc7*2; + } + speedcode[1] = speedvalue & 0xff; + speedcode[6] = speedvalue >> 8; + } + else + { + byte = (playeradr) >> 8; + fwrite8(songhandle, byte); + byte = (playeradr) & 0xff; + fwrite8(songhandle, byte); + } + + // Play address + byte = (playeradr+3) >> 8; + fwrite8(songhandle, byte); + byte = (playeradr+3) & 0xff; + fwrite8(songhandle, byte); + + // Number of subtunes + byte = 0x00; + fwrite8(songhandle, byte); + byte = songs; + fwrite8(songhandle, byte); + + // Default subtune + byte = 0x00; + fwrite8(songhandle, byte); + byte = 0x01; + fwrite8(songhandle, byte); + + // Song speed bits + byte = 0x00; + if ((ntsc) || (multiplier > 1) || (!multiplier)) byte = 0xff; + fwrite8(songhandle, byte); + fwrite8(songhandle, byte); + fwrite8(songhandle, byte); + fwrite8(songhandle, byte); + + // Songname etc. + fwrite(songname, sizeof songname, 1, songhandle); + fwrite(authorname, sizeof authorname, 1, songhandle); + fwrite(copyrightname, sizeof copyrightname, 1, songhandle); + + // Flags + byte = 0x00; + fwrite8(songhandle, byte); + if (ntsc) byte = 8; + else byte = 4; + // Set model for both SIDs + if (sidmodel) byte |= 32 + 128; + else byte |= 16 + 64; + fwrite8(songhandle, byte); + + // Relocation and second SID address + byte = 0x00; + fwrite8(songhandle, byte); + fwrite8(songhandle, byte); + fwrite8(songhandle, (sid2address & 0x0ff0) >> 4); + fwrite8(songhandle, byte); + + // Load address + if ((multiplier > 1) || (!multiplier)) + { + byte = (playeradr-10) & 0xff; + fwrite8(songhandle, byte); + byte = (playeradr-10) >> 8; + fwrite8(songhandle, byte); + } + else + { + byte = (playeradr) & 0xff; + fwrite8(songhandle, byte); + byte = (playeradr) >> 8; + fwrite8(songhandle, byte); + } + if ((multiplier > 1) || (!multiplier)) fwrite(speedcode, 10, 1, songhandle); + } + + fwrite(packeddata, packedsize, 1, songhandle); + fclose(songhandle); + +PRCLEANUP_S: + membuf_free(&src); + membuf_free(&dest); + + if (pattwork) free(pattwork); + if (songwork) free(songwork); + if (instrwork) free(instrwork); + printmainscreen(); + key = 0; + rawkey = 0; +} + diff --git a/src/greloc.h b/src/greloc.h index 42151a8..507a0ee 100644 --- a/src/greloc.h +++ b/src/greloc.h @@ -37,6 +37,7 @@ extern int tableerror; #endif void relocator(void); +void relocator_stereo(void); int testoverlap(int area1start, int area1size, int area2start, int area2size); int packpattern(unsigned char *dest, unsigned char *src, int rows); unsigned char swapnybbles(unsigned char n); diff --git a/src/gsong.c b/src/gsong.c index ad21fd7..d5123bc 100644 --- a/src/gsong.c +++ b/src/gsong.c @@ -21,6 +21,8 @@ int songlen_stereo[MAX_SONGS][MAX_CHN]; int highestusedpattern; int highestusedinstr; +int determinechannels(FILE* handle); + int savesong(void) { int c; @@ -212,6 +214,7 @@ void loadsong(void) FILE *handle; int maxChns = MAX_CHN; if (numsids == 1) maxChns = 3; + int channelstoload = maxChns; handle = fopen(songfilename, "rb"); @@ -233,10 +236,11 @@ void loadsong(void) fread(copyrightname, sizeof copyrightname, 1, handle); // Read songorderlists + channelstoload = determinechannels(handle); amount = fread8(handle); for (d = 0; d < amount; d++) { - for (c = 0; c < maxChns; c++) + for (c = 0; c < channelstoload; c++) { length = fread8(handle); loadsize = length; @@ -300,10 +304,11 @@ void loadsong(void) fread(copyrightname, sizeof copyrightname, 1, handle); // Read songorderlists + channelstoload = determinechannels(handle); amount = fread8(handle); for (d = 0; d < amount; d++) { - for (c = 0; c < maxChns; c++) + for (c = 0; c < channelstoload; c++) { length = fread8(handle); loadsize = length; @@ -399,10 +404,11 @@ void loadsong(void) fread(copyrightname, sizeof copyrightname, 1, handle); // Read songorderlists + channelstoload = determinechannels(handle); amount = fread8(handle); for (d = 0; d < amount; d++) { - for (c = 0; c < maxChns; c++) + for (c = 0; c < channelstoload; c++) { length = fread8(handle); loadsize = length; @@ -1497,7 +1503,7 @@ void countthispattern(void) int insertpattern(int p) { int c, d, e; - int tmp; + int tmp = 0; int maxChns = MAX_CHN; if (numsids == 1) maxChns = 3; @@ -1826,8 +1832,6 @@ void mergesong(void) int pattbase; int instrbase; int tablebase[MAX_TABLES]; - int maxChns = MAX_CHN; - if (numsids == 1) maxChns = 3; // Determine amount of patterns & instruments countpatternlengths(); @@ -1887,17 +1891,19 @@ void mergesong(void) int length; int amount; int loadsize; + int channelstoload; // Skip infotexts fseek(handle, sizeof songname + sizeof authorname + sizeof copyrightname, SEEK_CUR); // Read songorderlists + channelstoload = determinechannels(handle); amount = fread8(handle); if (amount + songbase > MAX_SONGS) goto ABORT; for (d = 0; d < amount; d++) { - for (c = 0; c < maxChns; c++) + for (c = 0; c < channelstoload; c++) { length = fread8(handle); loadsize = length; @@ -2016,3 +2022,33 @@ void mergesong(void) countpatternlengths(); songchange(); } + +int determinechannels(FILE* handle) +{ + int returnpos = ftell(handle); + int c, d; + int songs = fread8(handle); + unsigned char songbuffer[257]; + + for (d = 0; d < songs; d++) + { + for (c = 0; c < MAX_CHN; c++) + { + int loadsize = fread8(handle); + loadsize++; + memset(songbuffer, 0, 257); + fread(songbuffer, loadsize, 1, handle); + + // Check that each track of each song has a valid endmark. + // Should fail if it's a mono song (not certain) + if ((songbuffer[loadsize - 2] != 0xff) || (songbuffer[loadsize - 1] >= loadsize)) + { + fseek(handle, returnpos, SEEK_SET); + return 3; + } + } + } + + fseek(handle, returnpos, SEEK_SET); + return MAX_CHN; +} diff --git a/src/gsound.c b/src/gsound.c index 0ce36f3..f444d26 100644 --- a/src/gsound.c +++ b/src/gsound.c @@ -244,7 +244,14 @@ Uint32 sound_timer(void *userdata, SDL_TimerID timerID, Uint32 interval) void sound_playrout(void) { - playroutine(); + if (numsids == 1) + { + playroutine(); + } + else if (numsids == 2) + { + playroutine_stereo(); + } #ifdef USE_EXSID if (useexsid) diff --git a/src/gt2reloc.c b/src/gt2reloc.c deleted file mode 100644 index 2dc46af..0000000 --- a/src/gt2reloc.c +++ /dev/null @@ -1,447 +0,0 @@ -// -// GOATTRACKER v2.73 - gt2reloc (commandline relocator/packer) -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// - -#define GOATTRK2_C - -#ifdef __WIN32__ -#include -#endif - -#include "goattrk2.h" -#include "bme.h" - -int menu = 0; -int editmode = EDIT_PATTERN; -int recordmode = 1; -int followplay = 0; -int hexnybble = -1; -int stepsize = 4; -int autoadvance = 0; -int defaultpatternlength = 64; -int cursorflash = 0; -int cursorcolortable[] = {1,2,7,2}; -int exitprogram = 0; -int eacolumn = 0; -int eamode = 0; - -unsigned keypreset = KEY_TRACKER; -unsigned playerversion = 0; -int fileformat = FORMAT_PRG; -unsigned int zeropageadr = 0xfc; -unsigned int playeradr = 0x1000; -unsigned sidmodel = 0; -unsigned multiplier = 1; -unsigned adparam = 0x0f00; -unsigned ntsc = 0; -unsigned patterndispmode = 0; -unsigned sidaddress = 0xd400; -unsigned finevibrato = 1; -unsigned optimizepulse = 1; -unsigned optimizerealtime = 1; -unsigned customclockrate = 0; -unsigned usefinevib = 0; -unsigned mr = DEFAULTMIXRATE; -unsigned writer = 0; -unsigned interpolate = 0; -unsigned residdelay = 0; -float basepitch = 0.0f; - -unsigned monomode = 0; -unsigned numsids = 1; - -char configbuf[MAX_PATHNAME]; -char loadedsongfilename[MAX_FILENAME]; -char songfilename[MAX_FILENAME]; -char songfilter[MAX_FILENAME]; -char songpath[MAX_PATHNAME]; -char instrfilename[MAX_FILENAME]; -char instrfilter[MAX_FILENAME]; -char instrpath[MAX_PATHNAME]; -char packedpath[MAX_PATHNAME]; -char packedsongname[MAX_PATHNAME]; - -char *programname = "$VER: GoatTracker v2.77"; - -char textbuffer[MAX_PATHNAME]; - -extern unsigned char datafile[]; -COLORS colors; - -#ifdef __WIN32__ -FILE *STDOUT, *STDERR; -#else -#define STDOUT stdout -#define STDERR stderr -#endif - -void usage(void) -{ - fprintf(STDOUT, "Usage: GT2RELOC [options]\n"); - fprintf(STDOUT, "Options:\n"); - fprintf(STDOUT, "-Axx Set ADSR parameter for hardrestart in hex. DEFAULT=0F00\n"); - fprintf(STDOUT, "-Bx enable/disable buffered SID writes. DEFAULT=disabled\n"); - fprintf(STDOUT, "-Cx enable/disable zeropage ghost registers. DEFAULT=disabled\n"); - fprintf(STDOUT, "-Dx enable/disable sound effect support. DEFAULT=disabled\n"); - fprintf(STDOUT, "-Ex enable/disable volume change support. DEFAULT=disabled\n"); - fprintf(STDOUT, "-Fxx Set custom SID clock cycles per second (0 = use PAL/NTSC default)\n"); - fprintf(STDOUT, "-Gxx Set pitch of A-4 in Hz (0 = use default frequencytable, close to 440Hz)\n"); - fprintf(STDOUT, "-Hx enable/disable storing of author info. DEFAULT=disabled\n"); - fprintf(STDOUT, "-Ix enable/disable optimizations. DEFAULT=enabled\n"); - fprintf(STDOUT, "-Jx enable/disable full buffering. DEFAULT=disabled\n"); - fprintf(STDOUT, "-Lxx SID memory location in hex. DEFAULT=D400\n"); - fprintf(STDOUT, "-N Use NTSC timing\n"); - fprintf(STDOUT, "-Oxx Set pulseoptimization/skipping (0 = off, 1 = on) DEFAULT=on\n"); - fprintf(STDOUT, "-P Use PAL timing (DEFAULT)\n"); - fprintf(STDOUT, "-Rxx Set realtime-effect optimization/skipping (0 = off, 1 = on) DEFAULT=on\n"); - fprintf(STDOUT, "-Sxx Set speed multiplier (0 for 25Hz, 1 for 1x, 2 for 2x etc.) DEFAULT=1\n"); - fprintf(STDOUT, "-Vxx Set finevibrato conversion (0 = off, 1 = on) DEFAULT=on\n"); - fprintf(STDOUT, "-Wxx player memory location highbyte in hex. DEFAULT=1000\n"); - fprintf(STDOUT, "-Zxx zeropage memory location in hex. DEFAULT=FC\n"); - fprintf(STDOUT, "-? Show options\n"); -} - -int main(int argc, char **argv) -{ - int c; - -#ifdef __WIN32__ - /* - SDL_Init() reroutes stdout and stderr, either to stdout.txt and stderr.txt - or to nirwana. simply reopening these handles does, other than suggested on - some web pages, not work reliably - opening new files on CON using different - handles however does. - */ - STDOUT = fopen("CON", "w"); - STDERR = fopen("CON", "w"); -#endif - - programname += sizeof "$VER:"; - // Open datafile - io_openlinkeddatafile(datafile); - - // Reset channels/song - initchannels(); - clearsong(1,1,1,1,1); - - // get input- and output file names - if (argc >= 3) { - strcpy(songfilename, argv[1]); - strcpy(packedsongname, argv[2]); - } else { - usage(); - exit(-1); - } - - // Load song - if (strlen(songfilename)) { - loadsong(); - } else { - fprintf(STDERR, "error: no song filename given.\n"); - exit (-1); - } - - c = strlen(packedsongname); - if (strlen(packedsongname) <= 0) { - fprintf(STDERR, "error: no output filename given.\n"); - exit (-1); - } - - // determine output format from file extension of the output filename - c--; - while ((c > 0) && (packedsongname[c] != '.')) c--; - if (packedsongname[c] == '.') c++; - - if (!strcmp(&packedsongname[c], "sid")) { - fileformat = FORMAT_SID; - } else if (!strcmp(&packedsongname[c], "prg")) { - fileformat = FORMAT_PRG; - } else if (!strcmp(&packedsongname[c], "bin")) { - fileformat = FORMAT_BIN; - } else { - fileformat = FORMAT_PRG; - } - - fprintf(STDOUT, "%s Packer/Relocator\n", programname); - fprintf(STDOUT, "song file: %s\n", loadedsongfilename); - fprintf(STDOUT, "output file: %s\n", packedsongname); - fprintf(STDOUT, "output format: "); - if (fileformat == FORMAT_SID) { - fprintf(STDOUT, "sid\n"); - } else if (fileformat == FORMAT_BIN) { - fprintf(STDOUT, "bin\n"); - } else { - fprintf(STDOUT, "prg\n"); - } - - // Scan command line - for (c = 3; c < argc; c++) - { - #ifdef __WIN32__ - if ((argv[c][0] == '-') || (argv[c][0] == '/')) - #else - if (argv[c][0] == '-') - #endif - { - switch(toupper(argv[c][1])) - { - case '?': - return 0; - - case 'A': - sscanf(&argv[c][2], "%x", &adparam); - break; - - case 'G': - sscanf(&argv[c][2], "%f", &basepitch); - break; - - case 'L': - sscanf(&argv[c][2], "%x", &sidaddress); - break; - - case 'O': - sscanf(&argv[c][2], "%u", &optimizepulse); - break; - - case 'R': - sscanf(&argv[c][2], "%u", &optimizerealtime); - break; - - case 'V': - sscanf(&argv[c][2], "%u", &finevibrato); - break; - - case 'S': - sscanf(&argv[c][2], "%u", &multiplier); - break; - - // NTSC timing - case 'N': - ntsc = 1; - customclockrate = 0; - break; - // PAL timing - case 'P': - ntsc = 0; - customclockrate = 0; - break; - // custom clock rate - case 'F': - sscanf(&argv[c][2], "%u", &customclockrate); - break; - - // player options (first menu) - // 0: Buffered SID-writes - case 'B': - if (argv[c][2] == '1') { - playerversion |= PLAYER_BUFFERED; - } else { - playerversion &= ~PLAYER_BUFFERED; - } - break; - // 1: Sound effect support - case 'D': - if (argv[c][2] == '1') { - playerversion |= PLAYER_SOUNDEFFECTS; - } else { - playerversion &= ~PLAYER_SOUNDEFFECTS; - } - break; - // 2: Volume change support - case 'E': - if (argv[c][2] == '1') { - playerversion |= PLAYER_VOLUME; - } else { - playerversion &= ~PLAYER_VOLUME; - } - break; - // 3: Store author-info - case 'H': - if (argv[c][2] == '1') { - playerversion |= PLAYER_AUTHORINFO; - } else { - playerversion &= ~PLAYER_AUTHORINFO; - } - break; - // 4: Use zeropage ghostregs - case 'C': - if (argv[c][2] == '1') { - playerversion |= PLAYER_ZPGHOSTREGS; - } else { - playerversion &= ~PLAYER_ZPGHOSTREGS; - } - break; - // 5: Disable optimization - case 'I': - if (argv[c][2] == '1') { - playerversion &= ~PLAYER_NOOPTIMIZATION; - } else { - playerversion |= PLAYER_NOOPTIMIZATION; - } - break; - // 6: Full buffering - case 'J': - if (argv[c][2] == '1') { - playerversion &= ~PLAYER_FULLBUFFERED; - } else { - playerversion |= PLAYER_FULLBUFFERED; - } - break; - - // start address (second menu) - case 'W': - sscanf(&argv[c][2], "%x", &playeradr); - playeradr<<=8; - break; - - // zeropage address (third menu) - case 'Z': - sscanf(&argv[c][2], "%x", &zeropageadr); - break; - } - } - else - { - fprintf(STDERR, "error: unknown option\n"); - usage(); - exit(-1); - } - } - - // Init colorscheme - initcolorscheme(1); - - // Validate parameters - sidmodel &= 1; - adparam &= 0xffff; - zeropageadr &= 0xff; - playeradr &= 0xff00; - sidaddress &= 0xffff; - - if (multiplier > 16) multiplier = 16; - if ((finevibrato == 1) && (multiplier < 2)) usefinevib = 1; - if (finevibrato > 1) usefinevib = 1; - if (optimizepulse > 1) optimizepulse = 1; - if (optimizerealtime > 1) optimizerealtime = 1; - if (customclockrate < 100) customclockrate = 0; - - // Calculate frequencytable if necessary - if (basepitch < 0.0f) - basepitch = 0.0f; - if (basepitch > 0.0f) - calculatefreqtable(); - - // perform relocation - relocator(); - - // Exit - return 0; -} - -void waitkeymousenoupdate(void) -{ -} - -void getparam(FILE *handle, unsigned *value) -{ - char *configptr; - - for (;;) - { - if (feof(handle)) return; - fgets(configbuf, MAX_PATHNAME, handle); - if ((configbuf[0]) && (configbuf[0] != ';') && (configbuf[0] != ' ') && (configbuf[0] != 13) && (configbuf[0] != 10)) break; - } - - configptr = configbuf; - if (*configptr == '$') - { - *value = 0; - configptr++; - for (;;) - { - char c = tolower(*configptr++); - int h = -1; - - if ((c >= 'a') && (c <= 'f')) h = c - 'a' + 10; - if ((c >= '0') && (c <= '9')) h = c - '0'; - - if (h >= 0) - { - *value *= 16; - *value += h; - } - else break; - } - } - else - { - *value = 0; - for (;;) - { - char c = tolower(*configptr++); - int d = -1; - - if ((c >= '0') && (c <= '9')) d = c - '0'; - - if (d >= 0) - { - *value *= 10; - *value += d; - } - else break; - } - } -} - -void getfloatparam(FILE *handle, float *value) -{ - char *configptr; - - for (;;) - { - if (feof(handle)) return; - fgets(configbuf, MAX_PATHNAME, handle); - if ((configbuf[0]) && (configbuf[0] != ';') && (configbuf[0] != ' ') && (configbuf[0] != 13) && (configbuf[0] != 10)) break; - } - - configptr = configbuf; - *value = 0.0f; - sscanf(configptr, "%f", value); -} - -void calculatefreqtable() -{ - double basefreq = (double)basepitch * (16777216.0 / 985248.0) * pow(2.0, 0.25) / 32.0; - int c; - - for (c = 0; c < 8*12 ; c++) - { - double note = c; - double freq = basefreq * pow(2.0, note/12.0); - int intfreq = freq + 0.5; - if (intfreq > 0xffff) - intfreq = 0xffff; - freqtbllo[c] = intfreq & 0xff; - freqtblhi[c] = intfreq >> 8; - } -} - -#define GT2RELOC - -#include "greloc.c" diff --git a/src/loadtrk.seq b/src/loadtrk.seq index b053084..433e244 100644 --- a/src/loadtrk.seq +++ b/src/loadtrk.seq @@ -1,7 +1,8 @@ player.s altplayer.s +player_s.s +altplayer_s.s chargen.bin palette.bin -bcursor.bin cursor.bin loadtrk.bmp diff --git a/src/player_s.s b/src/player_s.s new file mode 100644 index 0000000..1bae006 --- /dev/null +++ b/src/player_s.s @@ -0,0 +1,1731 @@ +;------------------------------------------------------------------------------- +; GoatTracker V2.74 stereo playroutine +; +; NOTE: This playroutine source code does not fall under the GPL license! +; Use it, or song binaries created from it freely for any purpose, commercial +; or noncommercial. +; +; NOTE 2: This code is in the format of Magnus Lind's assembler from Exomizer. +; Does not directly compile on DASM etc. +;------------------------------------------------------------------------------- + + ;Defines will be inserted by the relocator here + +mt_temp1 = zpbase+0 +mt_temp2 = zpbase+1 + + ;Defines for the music data + ;Patterndata notes + +ENDPATT = $00 +INS = $00 +FX = $40 +FXONLY = $50 +NOTE = $60 +REST = $bd +KEYOFF = $be +KEYON = $bf +FIRSTPACKEDREST = $c0 +PACKEDREST = $00 + + ;Effects + +DONOTHING = $00 +PORTAUP = $01 +PORTADOWN = $02 +TONEPORTA = $03 +VIBRATO = $04 +SETAD = $05 +SETSR = $06 +SETWAVE = $07 +SETWAVEPTR = $08 +SETPULSEPTR = $09 +SETFILTPTR = $0a +SETFILTCTRL = $0b +SETFILTCUTOFF = $0c +SETMASTERVOL = $0d +SETFUNKTEMPO = $0e +SETTEMPO = $0f + + ;Orderlist commands + +REPEAT = $d0 +TRANSDOWN = $e0 +TRANS = $f0 +TRANSUP = $f0 +LOOPSONG = $ff + + ;Wave,pulse,filttable comands + +LOOPWAVE = $ff +LOOPPULSE = $ff +LOOPFILT = $ff +SETPULSE = $80 +SETFILTER = $80 +SETCUTOFF = $00 + + .ORG (base) + + ;Jump table + + jmp mt_init + jmp mt_play + .IF (SOUNDSUPPORT != 0) + jmp mt_playsfx + .ENDIF + .IF (VOLSUPPORT != 0) + jmp mt_setmastervol + .ENDIF + + ;Author info + + .IF (NOAUTHORINFO == 0) + +authorinfopos = base + $20 +checkpos1: + .IF ((authorinfopos - checkpos1) > 15) +mt_tick0jumptbl: + .BYTE (mt_tick0_0 % 256) + .BYTE (mt_tick0_12 % 256) + .BYTE (mt_tick0_12 % 256) + .BYTE (mt_tick0_34 % 256) + .BYTE (mt_tick0_34 % 256) + .BYTE (mt_tick0_5 % 256) + .BYTE (mt_tick0_6 % 256) + .BYTE (mt_tick0_7 % 256) + .BYTE (mt_tick0_8 % 256) + .BYTE (mt_tick0_9 % 256) + .BYTE (mt_tick0_a % 256) + .BYTE (mt_tick0_b % 256) + .BYTE (mt_tick0_c % 256) + .BYTE (mt_tick0_d % 256) + .BYTE (mt_tick0_e % 256) + .BYTE (mt_tick0_f % 256) + .ENDIF + +checkpos2: + .IF ((authorinfopos - checkpos2) > 4) +mt_effectjumptbl: + .BYTE (mt_effect_0 % 256) + .BYTE (mt_effect_12 % 256) + .BYTE (mt_effect_12 % 256) + .BYTE (mt_effect_3 % 256) + .BYTE (mt_effect_4 % 256) + .ENDIF + +checkpos3: + .IF ((authorinfopos - checkpos3) > 1) +mt_funktempotbl: + .BYTE (8,5) + .ENDIF + + ;This is pretty stupid way of filling left-out space, but .ORG + ;seemed to bug + +checkpos4: + .IF ((authorinfopos - checkpos4) > 0) .BYTE (0) .ENDIF +checkpos5: + .IF ((authorinfopos - checkpos5) > 0) .BYTE (0) .ENDIF +checkpos6: + .IF ((authorinfopos - checkpos6) > 0) .BYTE (0) .ENDIF + +mt_author: + + .BYTE (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) + .BYTE (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) + .ENDIF + + ;0 Instrument vibrato + +mt_tick0_0: + .IF (NOEFFECTS == 0) + .IF (NOINSTRVIB == 0) + lda mt_insvibparam-1,y + jmp mt_tick0_34 + .ELSE + .IF (NOVIB == 0) + jmp mt_tick0_34 + .ENDIF + .ENDIF + .ENDIF + + ;1,2 Portamentos + + +mt_tick0_12: + .IF (NOVIB == 0) + tay + lda #$00 + sta mt_chnvibtime,x + tya + .ENDIF + + ;3,4 Toneportamento, Vibrato + +mt_tick0_34: + .IF (NOEFFECTS == 0) + .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0)) + sta mt_chnparam,x + lda mt_chnnewfx,x + sta mt_chnfx,x + .ENDIF + rts + .ENDIF + + ;5 Set AD + +mt_tick0_5: + .IF (NOSETAD == 0) + sta mt_chnad,x + rts + .ENDIF + + ;6 Set Sustain/Release + +mt_tick0_6: + .IF (NOSETSR == 0) + sta mt_chnsr,x + rts + .ENDIF + + ;7 Set waveform + +mt_tick0_7: + .IF (NOSETWAVE == 0) + sta mt_chnwave,x + rts + .ENDIF + + ;8 Set wavepointer + +mt_tick0_8: + .IF (NOSETWAVEPTR == 0) + sta mt_chnwaveptr,x + .IF (NOWAVEDELAY == 0) + lda #$00 ;Make sure possible delayed + sta mt_chnwavetime,x ;waveform execution goes + .ENDIF ;correctly + rts + .ENDIF + + ;9 Set pulsepointer + +mt_tick0_9: + .IF (NOSETPULSEPTR == 0) + sta mt_chnpulseptr,x + lda #$00 ;Reset pulse step duration + sta mt_chnpulsetime,x + rts + .ENDIF + + ;a Set filtpointer + +mt_tick0_a: + .IF (NOSETFILTPTR == 0) + cpx #21 + bcs mt_tick0_a_sid2 + .IF (NOFILTERMOD == 0) + ldy #$00 + sty mt_filttime+1 + .ENDIF +mt_tick0_a_step: + sta mt_filtstep+1 + rts + .ENDIF + +mt_tick0_a_sid2: + .IF (NOSETFILTPTR == 0) + .IF (NOFILTERMOD == 0) + ldy #$00 + sty mt_filttime_sid2+1 + .ENDIF +mt_tick0_a_step_sid2: + sta mt_filtstep_sid2+1 + rts + .ENDIF + + ;b Set filtcontrol (channels & resonance) + +mt_tick0_b: + .IF (NOSETFILTCTRL == 0) + cpx #21 + bcs mt_tick0_b_sid2 + sta mt_filtctrl+1 + cmp #$00 + .IF (NOSETFILTPTR == 0) + beq mt_tick0_a_step ;If 0, stop also step-programming + .ELSE + bne mt_tick0_b_noset + sta mt_filtstep+1 +mt_tick0_b_noset: + .ENDIF + rts + .ENDIF + +mt_tick0_b_sid2: + .IF (NOSETFILTCTRL == 0) + sta mt_filtctrl_sid2+1 + cmp #$00 + .IF (NOSETFILTPTR == 0) + beq mt_tick0_a_step_sid2 ;If 0, stop also step-programming + .ELSE + bne mt_tick0_b_noset_sid2 + sta mt_filtstep_sid2+1 +mt_tick0_b_noset_sid2: + .ENDIF + rts + .ENDIF + + + ;c Set cutoff + +mt_tick0_c: + .IF (NOSETFILTCUTOFF == 0) + cpx #21 + bcs mt_tick0_c_sid2 + sta mt_filtcutoff+1 + rts + .ENDIF + +mt_tick0_c_sid2: + .IF (NOSETFILTCUTOFF == 0) + sta mt_filtcutoff_sid2+1 + rts + .ENDIF + + ;d Set mastervolume / timing mark + +mt_tick0_d: + .IF (NOSETMASTERVOL == 0) + .IF (NOAUTHORINFO == 0) + cmp #$10 + bcs mt_tick0_d_timing + .ENDIF +mt_setmastervol: + sta mt_masterfader+1 + rts + .IF (NOAUTHORINFO == 0) +mt_tick0_d_timing: + sta mt_author+31 + rts + .ENDIF + .ENDIF + + ;e Funktempo + +mt_tick0_e: + .IF (NOFUNKTEMPO == 0) + tay + lda mt_speedlefttbl-1,y + sta mt_funktempotbl + lda mt_speedrighttbl-1,y + sta mt_funktempotbl+1 + lda #$00 + .IF (NOCHANNELTEMPO == 0) + beq mt_tick0_f_setglobaltempo + .ENDIF + .ENDIF + + ;f Set Tempo + +mt_tick0_f: + .IF ((NOCHANNELTEMPO == 0) && (NOGLOBALTEMPO == 0)) + bmi mt_tick0_f_setchantempo ;Channel or global tempo? + .ENDIF +mt_tick0_f_setglobaltempo: + .IF (NOGLOBALTEMPO == 0) + sta mt_chntempo + sta mt_chntempo+7 + sta mt_chntempo+14 + sta mt_chntempo+21 + sta mt_chntempo+28 + sta mt_chntempo+35 + rts + .ENDIF +mt_tick0_f_setchantempo: + .IF (NOCHANNELTEMPO == 0) + and #$7f + sta mt_chntempo,x + rts + .ENDIF + + ;Continuous effect code + + ;0 Instrument vibrato + + .IF (NOINSTRVIB == 0) +mt_effect_0_delay: + dec mt_chnvibdelay,x +mt_effect_0_donothing: + jmp mt_done +mt_effect_0: beq mt_effect_0_donothing ;Speed 0 = no vibrato at all + lda mt_chnvibdelay,x + bne mt_effect_0_delay + .ELSE +mt_effect_0: +mt_effect_0_donothing: + jmp mt_done + .ENDIF + + ;4 Vibrato + +mt_effect_4: + .IF (NOVIB == 0) + .IF (NOCALCULATEDSPEED == 0) + lda mt_speedlefttbl-1,y + .IF (NONORMALSPEED == 0) + bmi mt_effect_4_nohibyteclear + ldy #$00 ;Clear speed highbyte + sty 1) + asl + sta mt_init+6 + asl + adc #$00 + .ENDIF + sta mt_initsongnum+1 + rts + + ;Play soundeffect -routine + + .IF (SOUNDSUPPORT != 0) + ;Sound FX init routine + +mt_playsfx: sta mt_playsfxlo+1 + sty mt_playsfxhi+1 + lda mt_chnsfx,x ;Need a priority check? + beq mt_playsfxok + tya ;Check address highbyte + cmp mt_chnsfxhi,x + bcc mt_playsfxskip ;Lower than current -> skip + bne mt_playsfxok ;Higher than current -> OK + lda mt_playsfxlo+1 ;Check address lowbyte + cmp mt_chnsfxlo,x + bcc mt_playsfxskip ;Lower than current -> skip +mt_playsfxok: lda #$01 + sta mt_chnsfx,x +mt_playsfxlo: lda #$00 + sta mt_chnsfxlo,x +mt_playsfxhi: lda #$00 + sta mt_chnsfxhi,x +mt_playsfxskip: rts + .ENDIF + + ;Set mastervolume -routine + + .IF ((VOLSUPPORT != 0) && (NOSETMASTERVOL != 0)) +mt_setmastervol: + sta mt_masterfader+1 + rts + .ENDIF + + ;Playroutine + +mt_play: ldx #$00 ;Channel index + + ;Song initialization + +mt_initsongnum: + ldy #$00 + bmi mt_filtstep + txa + ldx #NUMCHANNELS * 14 - 1 +mt_resetloop: + sta mt_chnsongptr,x ;Reset sequencer + voice + dex ;variables on all channels + bpl mt_resetloop + sta SIDBASE+$15 ;Reset filter cutoff lowbyte + sta SID2BASE+$15 + sta mt_filtctrl+1 ;Switch filter off & reset + sta mt_filtctrl_sid2+1 + .IF (NOFILTER == 0) + sta mt_filtstep+1 ;step-programming + sta mt_filtstep_sid2+1 + .ENDIF + stx mt_initsongnum+1 ;Reset initflag + tax + jsr mt_initchn + ldx #$07 + jsr mt_initchn + ldx #$0e + jsr mt_initchn + ldx #$15 + jsr mt_initchn + ldx #$1c + jsr mt_initchn + ldx #$23 +mt_initchn: + .IF (NUMSONGS > 1) + tya + iny + sta mt_chnsongnum,x ;Store index to songtable + .ENDIF +mt_defaulttempo: + lda #DEFAULTTEMPO ;Set default tempo + sta mt_chntempo,x + lda #$01 + sta mt_chncounter,x ;Reset counter + sta mt_chninstr,x ;Reset instrument + cpx #21 + bcs mt_initchn_sid2 + jmp mt_loadregswaveonly ;Load waveform +mt_initchn_sid2:jmp mt_loadregswaveonly_sid2 + + + ;Filter execution + +mt_filtstep: + .IF (NOFILTER == 0) + ldy #$00 ;See if filter stopped + beq mt_filtdone + .IF (NOFILTERMOD == 0) +mt_filttime: + lda #$00 ;See if time left for mod. + bne mt_filtmod ;step + .ENDIF +mt_newfiltstep: + lda mt_filttimetbl-1,y ;$80-> = set filt parameters + beq mt_setcutoff ;$00 = set cutoff + .IF (NOFILTERMOD == 0) + bpl mt_newfiltmod + .ENDIF +mt_setfilt: + asl ;Set passband + sta mt_filttype+1 + lda mt_filtspdtbl-1,y ;Set resonance/channel + sta mt_filtctrl+1 + lda mt_filttimetbl,y ;Check for cutoff setting + bne mt_nextfiltstep2 ;following immediately +mt_setcutoff2: + iny +mt_setcutoff: + lda mt_filtspdtbl-1,y ;Take cutoff value + sta mt_filtcutoff+1 + .IF (NOFILTERMOD == 0) + jmp mt_nextfiltstep +mt_newfiltmod: + sta mt_filttime+1 ;$01-$7f = new modulation step +mt_filtmod: + lda mt_filtspdtbl-1,y ;Take filt speed + clc + adc mt_filtcutoff+1 + sta mt_filtcutoff+1 + dec mt_filttime+1 + bne mt_storecutoff + .ENDIF +mt_nextfiltstep: + lda mt_filttimetbl,y ;Jump in filttable? +mt_nextfiltstep2: + cmp #LOOPFILT + iny + tya + bcc mt_nofiltjump + lda mt_filtspdtbl-1,y ;Take jump point +mt_nofiltjump: + sta mt_filtstep+1 +mt_filtdone: +mt_filtcutoff: + lda #$00 +mt_storecutoff: + sta SIDBASE+$16 + .ENDIF +mt_filtctrl: + lda #$00 + sta SIDBASE+$17 +mt_filttype: + lda #$00 +mt_masterfader: + ora #$0f ;Master volume fader + sta SIDBASE+$18 + + ;Second filter execution + +mt_filtstep_sid2: + .IF (NOFILTER == 0) + ldy #$00 ;See if filter stopped + beq mt_filtdone_sid2 + .IF (NOFILTERMOD == 0) +mt_filttime_sid2: + lda #$00 ;See if time left for mod. + bne mt_filtmod_sid2 ;step + .ENDIF +mt_newfiltstep_sid2: + lda mt_filttimetbl-1,y ;$80-> = set filt parameters + beq mt_setcutoff_sid2 ;$00 = set cutoff + .IF (NOFILTERMOD == 0) + bpl mt_newfiltmod_sid2 + .ENDIF +mt_setfilt_sid2: + asl ;Set passband + sta mt_filttype_sid2+1 + lda mt_filtspdtbl-1,y ;Set resonance/channel + sta mt_filtctrl_sid2+1 + lda mt_filttimetbl,y ;Check for cutoff setting + bne mt_nextfiltstep2_sid2 ;following immediately +mt_setcutoff2_sid2: + iny +mt_setcutoff_sid2: + lda mt_filtspdtbl-1,y ;Take cutoff value + sta mt_filtcutoff_sid2+1 + .IF (NOFILTERMOD == 0) + jmp mt_nextfiltstep_sid2 +mt_newfiltmod_sid2: + sta mt_filttime_sid2+1 ;$01-$7f = new modulation step +mt_filtmod_sid2: + lda mt_filtspdtbl-1,y ;Take filt speed + clc + adc mt_filtcutoff_sid2+1 + sta mt_filtcutoff_sid2+1 + dec mt_filttime_sid2+1 + bne mt_storecutoff_sid2 + .ENDIF +mt_nextfiltstep_sid2: + lda mt_filttimetbl,y ;Jump in filttable? +mt_nextfiltstep2_sid2: + cmp #LOOPFILT + iny + tya + bcc mt_nofiltjump_sid2 + lda mt_filtspdtbl-1,y ;Take jump point +mt_nofiltjump_sid2: + sta mt_filtstep_sid2+1 +mt_filtdone_sid2: +mt_filtcutoff_sid2: + lda #$00 +mt_storecutoff_sid2: + sta SID2BASE+$16 + .ENDIF +mt_filtctrl_sid2: + lda #$00 + sta SID2BASE+$17 +mt_filttype_sid2: + lda #$00 + ora mt_masterfader+1 ;Master volume fader + sta SID2BASE+$18 + + ;Channel execution + + jsr mt_execchn + ldx #$07 + jsr mt_execchn + ldx #$0e + jsr mt_execchn + ldx #$15 + jsr mt_execchn + ldx #$1c + jsr mt_execchn + ldx #$23 + +mt_execchn: + dec mt_chncounter,x ;See if tick 0 + beq mt_tick0 + + ;Ticks 1-n + +mt_notick0: + bpl mt_effects + lda mt_chntempo,x ;Reload tempo if negative + + .IF (NOFUNKTEMPO == 0) + cmp #$02 + bcs mt_nofunktempo ;Funktempo: bounce between + tay ;funktable indexes 0,1 + eor #$01 + sta mt_chntempo,x + lda mt_funktempotbl,y + sbc #$00 + .ENDIF + +mt_nofunktempo: + sta mt_chncounter,x +mt_effects: + jmp mt_waveexec + + ;Sequencer repeat + +mt_repeat: + .IF (NOREPEAT == 0) + sbc #REPEAT + inc mt_chnrepeat,x + cmp mt_chnrepeat,x + bne mt_nonewpatt +mt_repeatdone: + lda #$00 + sta mt_chnrepeat,x + beq mt_repeatdone2 + .ENDIF + + ;Tick 0 + +mt_tick0: + .IF (NOEFFECTS == 0) + ldy mt_chnnewfx,y ;Setup tick 0 FX jumps + lda mt_tick0jumptbl,y + sta mt_tick0jump1+1 + sta mt_tick0jump2+1 + .ENDIF + + ;Sequencer advance + +mt_checknewpatt: + lda mt_chnpattptr,x ;Fetch next pattern? + bne mt_nonewpatt +mt_sequencer: + ldy mt_chnsongnum,y + lda mt_songtbllo,y ;Get address of sequence + sta 0) || (NOFIRSTWAVECMD == 0)) + lda #$ff +mt_skipwave2: + sta mt_chngate,x ;Reset gateflag + .ELSE + inc mt_chngate,x + .ENDIF +mt_skipwave: + + .IF (NOPULSE == 0) + lda mt_inspulseptr-1,y ;Load pulseptr (if nonzero) + beq mt_skippulse + sta mt_chnpulseptr,x + .IF (NOPULSEMOD == 0) + lda #$00 ;Reset pulse step duration + sta mt_chnpulsetime,x + .ENDIF + .ENDIF +mt_skippulse: + .IF (NOFILTER == 0) + cpx #21 + lda mt_insfiltptr-1,y ;Load filtptr (if nonzero) + beq mt_skipfilt + bcs mt_loadfilt_sid2 +mt_loadfilt: + sta mt_filtstep+1 + .IF (NOFILTERMOD == 0) + lda #$00 + sta mt_filttime+1 + .ENDIF + bcc mt_skipfilt +mt_loadfilt_sid2: + sta mt_filtstep_sid2+1 + .IF (NOFILTERMOD == 0) + lda #$00 + sta mt_filttime_sid2+1 + .ENDIF + .ENDIF +mt_skipfilt: + + lda mt_inswaveptr-1,y ;Load waveptr + sta mt_chnwaveptr,x + + lda mt_insad-1,y ;Load Attack/Decay + sta mt_chnad,x + lda mt_inssr-1,y ;Load Sustain/Release + sta mt_chnsr,x + + .IF (NOEFFECTS == 0) + lda mt_chnnewparam,x ;Execute tick 0 FX after +mt_tick0jump1: + jsr mt_tick0_0 ;newnote init + .ENDIF + jmp mt_loadregs + + .IF (NOWAVECMD == 0) +mt_wavecmd: + jmp mt_execwavecmd + .ENDIF + + ;Tick 0 effect execution + +mt_nonewnoteinit: + .IF (NOEFFECTS == 0) + lda mt_chnnewparam,x ;No new note init: exec tick 0 +mt_tick0jump2: + jsr mt_tick0_0 ;FX, and wavetable afterwards + .ENDIF + + ;Wavetable execution + +mt_waveexec: + ldy mt_chnwaveptr,y + beq mt_wavedone + lda mt_wavetbl-1,y + .IF (NOWAVEDELAY == 0) + cmp #$10 ;0-15 used as delay + bcs mt_nowavedelay ;+ no wave change + cmp mt_chnwavetime,x + beq mt_nowavechange + inc mt_chnwavetime,x + bne mt_wavedone +mt_nowavedelay: + sbc #$10 + .ELSE + beq mt_nowavechange + .ENDIF + .IF (NOWAVECMD == 0) + cmp #$e0 + bcs mt_nowavechange + .ENDIF + sta mt_chnwave,x +mt_nowavechange: + lda mt_wavetbl,y + cmp #LOOPWAVE ;Check for wavetable jump + iny + tya + bcc mt_nowavejump + .IF (NOWAVECMD != 0) + clc + .ENDIF + lda mt_notetbl-1,y +mt_nowavejump: + sta mt_chnwaveptr,x + .IF (NOWAVEDELAY == 0) + lda #$00 + sta mt_chnwavetime,x + .ENDIF + + .IF (NOWAVECMD == 0) + lda mt_wavetbl-2,y + cmp #$e0 + bcs mt_wavecmd + .ENDIF + + lda mt_notetbl-2,y + + .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0)) + bne mt_wavefreq ;No frequency-change? + + ;No frequency-change / continuous effect execution + +mt_wavedone: + .IF (REALTIMEOPTIMIZATION != 0) + lda mt_chncounter,x ;No continuous effects on tick0 + .IF (PULSEOPTIMIZATION != 0) + beq mt_gatetimer + .ELSE + beq mt_done + .ENDIF + .ENDIF + .IF (NOEFFECTS == 0) + ldy mt_chnfx,y + .IF (NOWAVECMD == 0) + .IF (.DEFINED(mt_effectnum)) + sty mt_effectnum+1 + .ENDIF + .ENDIF + lda mt_effectjumptbl,y + sta mt_effectjump+1 + ldy mt_chnparam,y + .ELSE + ldy mt_chninstr,y + lda mt_insvibparam-1,y + tay + .ENDIF +mt_setspeedparam: + .IF (NOCALCULATEDSPEED != 0) + lda mt_speedrighttbl-1,y + sta 0) && (NUMNOHRINSTR > 0)) || (NUMLEGATOINSTR > 0)) + lda mt_chninstr,x + cmp #FIRSTNOHRINSTR ;Instrument order: + .IF (NUMLEGATOINSTR > 0) + bcs mt_nohr_legato ;With HR - no HR - legato + .ELSE + bcs mt_skiphr + .ENDIF + .ENDIF + .IF (NUMHRINSTR > 0) + lda #ADPARAM ;Hard restart + sta mt_chnad,x + lda #SRPARAM + sta mt_chnsr,x + .ENDIF +mt_skiphr: + lda #$fe +mt_setgate: + sta mt_chngate,x + + ;Check for end of pattern + +mt_rest: + iny + lda (mt_temp1),y + beq mt_endpatt + tya +mt_endpatt: + sta mt_chnpattptr,x + + ;Load voice registers + +mt_loadregs: + .IF (SOUNDSUPPORT != 0) + ldy mt_chnsfx,y + bne mt_sfxexec + .ENDIF + cpx #21 + bcs mt_loadregs_sid2 + lda mt_chnsr,x + sta SIDBASE+$06,x + lda mt_chnad,x + sta SIDBASE+$05,x + lda mt_chnpulselo,x + .IF (SIMPLEPULSE == 0) + sta SIDBASE+$02,x + lda mt_chnpulsehi,x + sta SIDBASE+$03,x + .ELSE + sta SIDBASE+$02,x + sta SIDBASE+$03,x + .ENDIF +mt_loadregswavefreq: + lda mt_chnfreqlo,x + sta SIDBASE+$00,x + lda mt_chnfreqhi,x + sta SIDBASE+$01,x +mt_loadregswaveonly: + lda mt_chnwave,x + and mt_chngate,x + sta SIDBASE+$04,x + rts + + .IF (NUMLEGATOINSTR > 0) +mt_nohr_legato: + cmp #FIRSTLEGATOINSTR + bcc mt_skiphr + bcs mt_rest + .ENDIF + +mt_loadregs_sid2: + lda mt_chnsr,x + sta SID2BASE-21+$06,x + lda mt_chnad,x + sta SID2BASE-21+$05,x + lda mt_chnpulselo,x + .IF (SIMPLEPULSE == 0) + sta SID2BASE-21+$02,x + lda mt_chnpulsehi,x + sta SID2BASE-21+$03,x + .ELSE + sta SID2BASE-21+$02,x + sta SID2BASE-21+$03,x + .ENDIF +mt_loadregswavefreq_sid2: + lda mt_chnfreqlo,x + sta SID2BASE-21+$00,x + lda mt_chnfreqhi,x + sta SID2BASE-21+$01,x +mt_loadregswaveonly_sid2: + lda mt_chnwave,x + and mt_chngate,x + sta SID2BASE-21+$04,x + rts + + ;Sound FX code + + .IF (SOUNDSUPPORT != 0) + +mt_sfxexec: lda mt_chnsfxlo,x + sta Date: Sun, 5 Jul 2026 15:36:10 +0200 Subject: [PATCH 08/15] Apply changes from fork https://github.com/jansalleine/gt2fork/commit/453521b9366789788b6e3d5169b25bbf87afe44d https://github.com/jansalleine/gt2fork/commit/8560091afa3a8041ef50333dd293d1c653b583ff --- src/gconsole.c | 10 ++++++++ src/gconsole.h | 2 +- src/goattrk2.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++--- src/goattrk2.h | 2 ++ src/gpattern.c | 10 ++++---- src/greloc.c | 32 ++++++++++++------------ src/gsong.c | 44 +++++++++++++++++++++++++++++++++ src/gsound.c | 4 +-- 8 files changed, 144 insertions(+), 27 deletions(-) diff --git a/src/gconsole.c b/src/gconsole.c index 047d49e..b45691d 100644 --- a/src/gconsole.c +++ b/src/gconsole.c @@ -16,6 +16,7 @@ unsigned char *chardata = NULL; int key = 0; int rawkey = 0; int shiftpressed = 0; +int altpressed = 0; int cursorflashdelay = 0; int mouseb = 0; int prevmouseb = 0; @@ -475,7 +476,16 @@ void getkey(void) shiftpressed = 0; if ((win_keystate[SDL_SCANCODE_LSHIFT])||(win_keystate[SDL_SCANCODE_RSHIFT])|| (win_keystate[SDL_SCANCODE_LCTRL])||(win_keystate[SDL_SCANCODE_RCTRL])) + { shiftpressed = 1; + } + + altpressed = 0; + if ((win_keystate[SDL_SCANCODE_LALT])|| + (win_keystate[SDL_SCANCODE_RALT])) + { + altpressed = 1; + } if (rawkey == SDL_SCANCODE_KP_ENTER) { diff --git a/src/gconsole.h b/src/gconsole.h index 493240f..2e8f217 100644 --- a/src/gconsole.h +++ b/src/gconsole.h @@ -44,7 +44,7 @@ void getkey(void); void initDisplayPositions(void); #ifndef GCONSOLE_C -extern int key, rawkey, shiftpressed, cursorflashdelay; +extern int key, rawkey, shiftpressed, altpressed, cursorflashdelay; extern int mouseb, prevmouseb; extern int mouseheld; extern int mousex, mousey; diff --git a/src/goattrk2.c b/src/goattrk2.c index 23b13e5..b030f9e 100644 --- a/src/goattrk2.c +++ b/src/goattrk2.c @@ -69,6 +69,7 @@ unsigned combwaves = 1; float basepitch = 0.0f; float filterbias = 0.5f; float equaldivisionsperoctave = 12.0f; +float panning = 1.0f; int tuningcount = 0; double tuning[96]; @@ -186,6 +187,7 @@ int main(int argc, char **argv) getparam(configfile, &patterndispmode); getparam(configfile, &sidaddress); getparam(configfile, &sid2address); + getfloatparam(configfile, &panning); getparam(configfile, &finevibrato); getparam(configfile, &optimizepulse); getparam(configfile, &optimizerealtime); @@ -386,6 +388,8 @@ int main(int argc, char **argv) if (customclockrate < 100) customclockrate = 0; if (defaultpatternlength < 1) defaultpatternlength = 1; if (defaultpatternlength > MAX_PATTROWS) defaultpatternlength = MAX_PATTROWS; + if (panning < 0) panning = 0; + if (panning > 1) panning = 1; if (combwaves < 0) combwaves = 0; else if (combwaves > 2) combwaves = 2; if (filterbias < 0.0) filterbias = 0.0; @@ -485,6 +489,7 @@ int main(int argc, char **argv) ";Pattern display mode (0 = decimal, 1 = hex, 2 = decimal w/dots, 3 = hex w/dots)\n%d\n\n" ";SID baseaddress\n$%04x\n\n" ";2nd SID baseaddress\n$%04x\n\n" + ";Panning in stereo mode (0.00 - 1.00; 0 = channels reversed, 0.5 = mono, 1 = seperated)\n%.2f\n\n" ";Finevibrato mode (0 = off, 1 = on)\n%d\n\n" ";Pulseskipping (0 = off, 1 = on)\n%d\n\n" ";Realtime effect skipping (0 = off, 1 = on)\n%d\n\n" @@ -516,6 +521,7 @@ int main(int argc, char **argv) patterndispmode, sidaddress, sid2address, + panning, finevibrato, optimizepulse, optimizerealtime, @@ -1201,6 +1207,15 @@ void generalcommands(void) case KEY_F11: save(); break; + + case KEY_M: + if (altpressed) + { + key = 0; + rawkey = 0; + switchMode(); + } + break; } } @@ -1343,7 +1358,7 @@ void clear(void) int selectdone = 0; unsigned olddpl = defaultpatternlength; - printtext(dpos.statusBottomX+20, dpos.statusBottomY, 15,"Pattern length:"); + printtext(dpos.statusBottomX+20, dpos.statusBottomY, 15, "Pattern length:"); while (!selectdone) { if (patterndispmode) @@ -1354,7 +1369,7 @@ void clear(void) { sprintf(textbuffer, "%02d ", defaultpatternlength); } - printtext(dpos.statusBottomX+35, dpos.statusBottomY, 15, textbuffer); + printtext(dpos.statusBottomX+35, dpos.statusBottomY, colors.CTITLE, textbuffer); waitkey(); switch(rawkey) { @@ -1728,5 +1743,51 @@ void readscalatuningfile() } } fclose(scalatuningfile); - } + } +} + +void switchMode(void) +{ + printtextcp( + dpos.statusBottomX+29, + dpos.statusBottomY, + colors.CTITLE, + "Switch mono / stereo mode (y/n)?" + ); + printtextcp( + dpos.statusBottomX+29, + dpos.statusBottomY+1, + colors.CEDIT, + "!!!Songdata will be cleared!!!" + ); + + waitkey(); + + printblank(dpos.statusBottomX, dpos.statusBottomY, 58); + printblank(dpos.statusBottomX, dpos.statusBottomY+1, 58); + + if ((key == 'y') || (key == 'Y')) + { + printf("switchMode: yes\n"); + + memset(songfilename, 0, sizeof songfilename); + + // SDL_PauseAudio(1); + numsids ^= 3; + clearsong(1, 1, 1, 1, 1); + + sound_init( + mr, + writer, + sidmodel, + ntsc, + multiplier, + interpolate, + customclockrate, exsid, filterbias, combwaves + ); + initDisplayPositions(); + printmainscreen(); + } + key = 0; + rawkey = 0; } diff --git a/src/goattrk2.h b/src/goattrk2.h index f2dca16..bbce2bd 100644 --- a/src/goattrk2.h +++ b/src/goattrk2.h @@ -68,6 +68,7 @@ extern unsigned ntsc; extern unsigned patterndispmode; extern unsigned sidaddress; extern unsigned sid2address; +extern float panning; extern unsigned finevibrato; extern unsigned optimizepulse; extern unsigned optimizerealtime; @@ -119,5 +120,6 @@ void editadsr(void); void calculatefreqtable(void); void setspecialnotenames(void); void readscalatuningfile(void); +void switchMode(void); #endif diff --git a/src/gpattern.c b/src/gpattern.c index 16ae099..e5fa31f 100644 --- a/src/gpattern.c +++ b/src/gpattern.c @@ -99,14 +99,14 @@ void patterncommands(void) case KEY_TRACKER: for (i = 0; i < sizeof(notekeytbl1); i++) { - if ((rawkey == notekeytbl1[i]) && (!epcolumn) && (!shiftpressed)) + if ((rawkey == notekeytbl1[i]) && (!epcolumn) && (!shiftpressed) && (!altpressed)) { newnote = FIRSTNOTE+i+epoctave*12; } } for (i = 0; i < sizeof(notekeytbl2); i++) { - if ((rawkey == notekeytbl2[i]) && (!epcolumn) && (!shiftpressed)) + if ((rawkey == notekeytbl2[i]) && (!epcolumn) && (!shiftpressed) && (!altpressed)) { newnote = FIRSTNOTE+i+(epoctave+1)*12; } @@ -116,7 +116,7 @@ void patterncommands(void) case KEY_DMC: for (i = 0; i < sizeof(dmckeytbl); i++) { - if ((rawkey == dmckeytbl[i]) && (!epcolumn) && (!shiftpressed)) + if ((rawkey == dmckeytbl[i]) && (!epcolumn) && (!shiftpressed) && (!altpressed)) { newnote = FIRSTNOTE+i+epoctave*12; } @@ -126,14 +126,14 @@ void patterncommands(void) case KEY_JANKO: for (i = 0; i < sizeof(jankokeytbl1); i++) { - if ((rawkey == jankokeytbl1[i]) && (!epcolumn) && (!shiftpressed)) + if ((rawkey == jankokeytbl1[i]) && (!epcolumn) && (!shiftpressed) && (!altpressed)) { newnote = FIRSTNOTE+i+epoctave*12; } } for (i = 0; i < sizeof(jankokeytbl2); i++) { - if ((rawkey == jankokeytbl2[i]) && (!epcolumn) && (!shiftpressed)) + if ((rawkey == jankokeytbl2[i]) && (!epcolumn) && (!shiftpressed) && (!altpressed)) { newnote = FIRSTNOTE+i+(epoctave+1)*12; } diff --git a/src/greloc.c b/src/greloc.c index 4b6822a..63f076a 100644 --- a/src/greloc.c +++ b/src/greloc.c @@ -241,7 +241,7 @@ void relocator(void) { sprintf(textbuffer, "ILLEGAL SONG RESTART POSITION! (SUBTUNE %02X, CHANNEL %d)", c, d+1); clearscreen(); - printtextc(MAX_ROWS/2, 15, textbuffer); + printtextc(MAX_ROWS/2, colors.CTITLE, textbuffer); fliptoscreen(); waitkeynoupdate(); goto PRCLEANUP; @@ -417,7 +417,7 @@ void relocator(void) case CMD_FUNKTEMPO: sprintf(textbuffer, "ILLEGAL WAVETABLE COMMAND (ROW %02X, COMMAND %X)", c+1, ltable[WTBL][c] - WAVECMD); clearscreen(); - printtextc(MAX_ROWS/2, 15, textbuffer); + printtextc(MAX_ROWS/2, colors.CTITLE, textbuffer); fliptoscreen(); waitkeynoupdate(); goto PRCLEANUP; @@ -494,7 +494,7 @@ void relocator(void) strcat(textbuffer, ")"); break; } - printtextc(MAX_ROWS/2, 15, textbuffer); + printtextc(MAX_ROWS/2, colors.CTITLE, textbuffer); fliptoscreen(); waitkeynoupdate(); @@ -711,7 +711,7 @@ void relocator(void) { clearscreen(); sprintf(textbuffer, "PATTERN %02X IS TOO COMPLEX (OVER 256 BYTES PACKED)!", c); - printtextc(MAX_ROWS/2, 15, textbuffer); + printtextc(MAX_ROWS/2, colors.CTITLE, textbuffer); fliptoscreen(); waitkeynoupdate(); goto PRCLEANUP; @@ -928,13 +928,13 @@ void relocator(void) if (nofilter) filttblsize = 0; sprintf(textbuffer, "SELECT START ADDRESS: (CURSORS=MOVE, ENTER=ACCEPT, ESC=CANCEL)"); - printtext(1, 11, 15, textbuffer); + printtext(1, 11, colors.CTITLE, textbuffer); selectdone = 0; while (!selectdone) { sprintf(textbuffer, "$%04X", playeradr); - printtext(1, 12, 10, textbuffer); + printtext(1, 12, colors.CEDIT, textbuffer); fliptoscreen(); waitkeynoupdate(); @@ -980,7 +980,7 @@ void relocator(void) if (selectdone == -1) goto PRCLEANUP; sprintf(textbuffer, "SELECT ZEROPAGE ADDRESS: (CURSORS=MOVE, ENTER=ACCEPT, ESC=CANCEL)"); - printtext(1, 14, 15, textbuffer); + printtext(1, 14, colors.CTITLE, textbuffer); selectdone = 0; while (!selectdone) @@ -1012,7 +1012,7 @@ void relocator(void) sprintf(textbuffer, "$%02X-$%02X (ghostregs start at %02X)", zeropageadr, zeropageadr+26, zeropageadr); } - printtext(1, 15, 10, textbuffer); + printtext(1, 15, colors.CEDIT, textbuffer); fliptoscreen(); waitkeynoupdate(); @@ -2296,7 +2296,7 @@ void relocator_stereo(void) { sprintf(textbuffer, "ILLEGAL SONG RESTART POSITION! (SUBTUNE %02X, CHANNEL %d)", c, d+1); clearscreen(); - printtextc(MAX_ROWS/2, 15, textbuffer); + printtextc(MAX_ROWS/2, colors.CTITLE, textbuffer); fliptoscreen(); waitkeynoupdate(); goto PRCLEANUP_S; @@ -2466,7 +2466,7 @@ void relocator_stereo(void) case CMD_FUNKTEMPO: sprintf(textbuffer, "ILLEGAL WAVETABLE COMMAND (ROW %02X, COMMAND %X)", c+1, ltable[WTBL][c] - WAVECMD); clearscreen(); - printtextc(MAX_ROWS/2, 15, textbuffer); + printtextc(MAX_ROWS/2, colors.CTITLE, textbuffer); fliptoscreen(); waitkeynoupdate(); goto PRCLEANUP_S; @@ -2543,7 +2543,7 @@ void relocator_stereo(void) strcat(textbuffer, ")"); break; } - printtextc(MAX_ROWS/2, 15, textbuffer); + printtextc(MAX_ROWS/2, colors.CTITLE, textbuffer); fliptoscreen(); waitkeynoupdate(); @@ -2763,7 +2763,7 @@ void relocator_stereo(void) { clearscreen(); sprintf(textbuffer, "PATTERN %02X IS TOO COMPLEX (OVER 256 BYTES PACKED)!", c); - printtextc(MAX_ROWS/2, 15, textbuffer); + printtextc(MAX_ROWS/2, colors.CTITLE, textbuffer); fliptoscreen(); waitkeynoupdate(); goto PRCLEANUP_S; @@ -2980,13 +2980,13 @@ void relocator_stereo(void) if (nofilter) filttblsize = 0; sprintf(textbuffer, "SELECT START ADDRESS: (CURSORS=MOVE, ENTER=ACCEPT, ESC=CANCEL)"); - printtext(1, 10, 15, textbuffer); + printtext(1, 10, colors.CTITLE, textbuffer); selectdone = 0; while (!selectdone) { sprintf(textbuffer, "$%04X", playeradr); - printtext(1, 11, 10, textbuffer); + printtext(1, 11, colors.CEDIT, textbuffer); fliptoscreen(); waitkeynoupdate(); @@ -3032,7 +3032,7 @@ void relocator_stereo(void) if (selectdone == -1) goto PRCLEANUP_S; sprintf(textbuffer, "SELECT ZEROPAGE ADDRESS: (CURSORS=MOVE, ENTER=ACCEPT, ESC=CANCEL)"); - printtext(1, 13, 15, textbuffer); + printtext(1, 13, colors.CTITLE, textbuffer); selectdone = 0; while (!selectdone) @@ -3064,7 +3064,7 @@ void relocator_stereo(void) sprintf(textbuffer, "$%02X-$%02X (ghostregs start at %02X)", zeropageadr, zeropageadr+26, zeropageadr); } - printtext(1, 14, 10, textbuffer); + printtext(1, 14, colors.CEDIT, textbuffer); fliptoscreen(); waitkeynoupdate(); diff --git a/src/gsong.c b/src/gsong.c index d5123bc..da35d11 100644 --- a/src/gsong.c +++ b/src/gsong.c @@ -901,6 +901,50 @@ void loadsong(void) if (!instr[c].firstwave) instr[c].gatetimer |= 0x40; } } + + // If was a mono song, create empty orderlists for channels 4-6 + if (channelstoload < MAX_CHN) + { + int emptypatt = MAX_PATT-1; + + findusedpatterns(); + for (c = 0; c < MAX_PATT; c++) + { + if (!pattused[c]) + { + int d; + int ok = 1; + for (d = 0; d < pattlen[c]; d++) + { + if ((pattern[c][d*4] != REST) || (pattern[c][d*4+1] != 0x00) || + (pattern[c][d*4+2] != 0x00) || (pattern[c][d*4+3] != 0x00)) + ok = 0; + } + + if (ok) + { + emptypatt = c; + break; + } + } + } + + for (c = 0; c < MAX_SONGS; c++) + { + if (songlen_stereo[c][0]) + { + int d; + for (d = channelstoload; d < MAX_CHN; d++) + { + songorder_stereo[c][d][0] = emptypatt; + songorder_stereo[c][d][1] = 0xff; + songorder_stereo[c][d][2] = 0x00; + songlen_stereo[c][d] = 1; + } + } + } + songchange(); + } } } diff --git a/src/gsound.c b/src/gsound.c index f444d26..73bf3f2 100644 --- a/src/gsound.c +++ b/src/gsound.c @@ -311,8 +311,8 @@ void sound_mixer(Sint32 *dest, unsigned samples) { for (c = 0; c < samples; c++) { - dest[c*2] = lbuffer[c]; - dest[c*2+1] = rbuffer[c]; + dest[c*2] = lbuffer[c] * panning + rbuffer[c] * (1-panning); + dest[c*2+1] = rbuffer[c] * panning + lbuffer[c] * (1-panning); } } } From 60ca6b632dda4a093c18482112b88fc5f97c94c2 Mon Sep 17 00:00:00 2001 From: Leandro Nini Date: Sun, 5 Jul 2026 16:49:12 +0200 Subject: [PATCH 09/15] Misc stuff --- AUTHORS | 12 ++- CMakeLists.txt | 1 - src/bme/bme.h | 1 - src/bme/bme_kbd.c | 209 ---------------------------------------------- src/bme/bme_kbd.h | 10 --- src/gconsole.c | 2 - src/gdisplay.c | 4 +- src/ghelp.c | 8 +- src/goattrk2.c | 23 +++-- 9 files changed, 32 insertions(+), 238 deletions(-) delete mode 100644 src/bme/bme_kbd.c delete mode 100644 src/bme/bme_kbd.h diff --git a/AUTHORS b/AUTHORS index 5342f21..f20d326 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,3 +1,9 @@ -Lasse Öörni: original GoatTracker -Leaf Corcoran: MIDI input -Leandro Nini: +Editor by Lasse Öörni and Jan Wassermann. +Music playroutines by Lasse Öörni. +MIDI input by Leaf Corcoran and Leandro Nini +Uses 6510 crossassembler from Exomizer2 beta by Magnus Lind. +Uses the SDL3 library. +Command quick reference by Simon Bennett. +Patches and further development by Stefan A. Haubenthal, Valerio Cannone, +Raine M. Ekman, Tero Lindeman, Henrik Paulini, Groepaz and Leandro Nini. +Microtonal support by Birgit Jauernig. diff --git a/CMakeLists.txt b/CMakeLists.txt index b2e9a48..0d58e3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,7 +47,6 @@ set(LOADTRK_SOURCES src/bme/bme_snd.c src/bme/bme_win.c src/bme/bme_mou.c - src/bme/bme_kbd.c src/bme/bme_io.c src/bme/bme_end.c src/bme/bme.c diff --git a/src/bme/bme.h b/src/bme/bme.h index 787dfe2..e479815 100644 --- a/src/bme/bme.h +++ b/src/bme/bme.h @@ -10,7 +10,6 @@ #include "bme_snd.h" #include "bme_gfx.h" #include "bme_win.h" -#include "bme_kbd.h" #include "bme_mou.h" #include "bme_io.h" #include "bme_end.h" diff --git a/src/bme/bme_kbd.c b/src/bme/bme_kbd.c deleted file mode 100644 index cb811da..0000000 --- a/src/bme/bme_kbd.c +++ /dev/null @@ -1,209 +0,0 @@ -// -// BME (Blasphemous Multimedia Engine) keyboard module -// - -#include -#include -#include - -#include -#include "bme_main.h" -#include "bme_cfg.h" -#include "bme_win.h" -#include "bme_io.h" -#include "bme_err.h" - -int kbd_init(void); -void kbd_uninit(void); -int kbd_waitkey(void); -int kbd_getkey(void); -int kbd_checkkey(int rawcode); -int kbd_getascii(void); -unsigned kbd_getvirtualkey(void); -char *kbd_getkeyname(int rawcode); - -static KEY keyname[] = {{KEY_BACKSPACE, "BACKSPACE"}, - {KEY_CAPSLOCK, "CAPSLOCK"}, - {KEY_ENTER, "ENTER"}, - {KEY_ESC, "ESC"}, - {KEY_NUMLOCK, "NUMLOCK"}, - {KEY_LEFTSHIFT, "SHIFT"}, - {KEY_RIGHTSHIFT, "SHIFT"}, - {KEY_SCROLLLOCK, "SCR. LOCK"}, - {KEY_SPACE, "SPACE"}, - {KEY_TAB, "TAB"}, - {KEY_F1, "F1"}, - {KEY_F2, "F2"}, - {KEY_F3, "F3"}, - {KEY_F4, "F4"}, - {KEY_F5, "F5"}, - {KEY_F6, "F6"}, - {KEY_F7, "F7"}, - {KEY_F8, "F8"}, - {KEY_F9, "F9"}, - {KEY_F10, "F10"}, - {KEY_F11, "F11"}, - {KEY_F12, "F12"}, - {KEY_A, "A"}, - {KEY_N, "N"}, - {KEY_B, "B"}, - {KEY_O, "O"}, - {KEY_C, "C"}, - {KEY_P, "P"}, - {KEY_D, "D"}, - {KEY_Q, "Q"}, - {KEY_E, "E"}, - {KEY_R, "R"}, - {KEY_F, "F"}, - {KEY_S, "S"}, - {KEY_G, "G"}, - {KEY_T, "T"}, - {KEY_H, "H"}, - {KEY_U, "U"}, - {KEY_I, "I"}, - {KEY_V, "V"}, - {KEY_J, "J"}, - {KEY_W, "W"}, - {KEY_K, "K"}, - {KEY_X, "X"}, - {KEY_L, "L"}, - {KEY_Y, "Y"}, - {KEY_M, "M"}, - {KEY_Z, "Z"}, - {KEY_1, "1"}, - {KEY_2, "2"}, - {KEY_3, "3"}, - {KEY_4, "4"}, - {KEY_5, "5"}, - {KEY_6, "6"}, - {KEY_7, "7"}, - {KEY_8, "8"}, - {KEY_9, "9"}, - {KEY_0, "0"}, - {KEY_MINUS, "-"}, - {KEY_EQUAL, "="}, - {KEY_BRACKETL, "["}, - {KEY_BRACKETR, "]"}, - {KEY_SEMICOLON, ";"}, - {KEY_APOST1, "'"}, - {KEY_APOST2, "`"}, - {KEY_COMMA, ","}, - {KEY_COLON, "."}, - {KEY_SLASH, "/"}, - {KEY_BACKSLASH, "\\"}, - {KEY_ALT, "ALT"}, - {KEY_CTRL, "CTRL"}, - {KEY_DEL, "DELETE"}, - {KEY_DOWN, "CRS. DOWN"}, - {KEY_END, "END"}, - {KEY_HOME, "HOME"}, - {KEY_INS, "INSERT"}, - {KEY_LEFT, "CRS. LEFT"}, - {KEY_PGDN, "PAGE DOWN"}, - {KEY_PGUP, "PAGE UP"}, - {KEY_RIGHT, "CRS. RIGHT"}, - {KEY_UP, "CRS. UP"}, - {KEY_WINDOWSL, "WINDOWS KEY"}, - {KEY_WINDOWSR, "WINDOWS KEY"}, - {KEY_MENU, "MENU KEY"}, - {0xff, "?"}}; - -int kbd_init(void) -{ - return BME_OK; -} - -void kbd_uninit(void) -{ -} - -int kbd_waitkey(void) -{ - int index; - - win_asciikey = 0; - for (;;) - { - win_checkmessages(); - - for (index = 0; index < SDL_SCANCODE_COUNT; index++) - { - if (win_keytable[index]) - { - win_keytable[index] = 0; - return index; - } - } - - SDL_Delay(15); - } -} - -int kbd_getkey(void) -{ - int index; - - for (index = 0; index < SDL_SCANCODE_COUNT; index++) - { - if (win_keytable[index]) - { - win_keytable[index] = 0; - return index; - } - } - return 0; -} - -int kbd_checkkey(int rawcode) -{ - if (rawcode >= SDL_SCANCODE_COUNT) return 0; - if (win_keytable[rawcode]) - { - win_keytable[rawcode] = 0; - return 1; - } - return 0; -} - -int kbd_getascii(void) -{ - int key; - - if (win_asciikey) - { - key = win_asciikey; - win_asciikey = 0; - return key; - } - else return 0; -} - -unsigned kbd_getvirtualkey(void) -{ - unsigned key; - - if (win_virtualkey) - { - key = win_virtualkey; - win_virtualkey = 0; - return key; - } - else return 0; -} - -char *kbd_getkeyname(int rawcode) -{ - KEY *ptr = &keyname[0]; - - while (ptr->rawcode != 255) - { - if (ptr->rawcode == rawcode) - { - return ptr->name; - } - ptr++; - } - return ptr->name; -} - - diff --git a/src/bme/bme_kbd.h b/src/bme/bme_kbd.h deleted file mode 100644 index 98cd3e9..0000000 --- a/src/bme/bme_kbd.h +++ /dev/null @@ -1,10 +0,0 @@ -// BME keyboard functions header file - -int kbd_init(void); -void kbd_uninit(void); -int kbd_waitkey(void); -int kbd_getkey(void); -int kbd_checkkey(int rawcode); -int kbd_getascii(void); -unsigned kbd_getvirtualkey(void); -char *kbd_getkeyname(int rawcode); diff --git a/src/gconsole.c b/src/gconsole.c index b45691d..56372bf 100644 --- a/src/gconsole.c +++ b/src/gconsole.c @@ -74,8 +74,6 @@ int initscreen(void) unsigned xsize = MAX_COLUMNS * 8; unsigned ysize = MAX_ROWS * 16; - printf("xsize: %d, ysize: %d\n", xsize, ysize); - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) return 0; win_openwindow(xsize, ysize, "LoadTracker", NULL); diff --git a/src/gdisplay.c b/src/gdisplay.c index 509db0d..9f33875 100644 --- a/src/gdisplay.c +++ b/src/gdisplay.c @@ -232,11 +232,11 @@ void printstatus(void) textbuffer[3] = 0; if (p%stepsize) { - printtext(dpos.patternsX+c*13, dpos.patternsY+1+d, colors.CNORMAL, textbuffer); + printtext(dpos.patternsX-1+c*13, dpos.patternsY+1+d, colors.CNORMAL, textbuffer); } else { - printtext(dpos.patternsX+c*13, dpos.patternsY+1+d, colors.CCOMMAND, textbuffer); + printtext(dpos.patternsX-1+c*13, dpos.patternsY+1+d, colors.CCOMMAND, textbuffer); } if (color == colors.CNORMAL) color2 = colors.CCOMMAND; diff --git a/src/ghelp.c b/src/ghelp.c index 72928e8..fe0ad3c 100644 --- a/src/ghelp.c +++ b/src/ghelp.c @@ -37,8 +37,10 @@ void onlinehelp(int standalone,int context) "SHIFT+F5-F6 Change speed multiplier", "SHIFT+F7 Change hardrestart ADSR", "SHIFT+F8 Switch between 6581/8580 SID", + "SHIFT+F9 Mix to mono (in STEREO mode)", "SHIFT+F10 Merge-load song", "SHIFT+, . Move song startpos & restart", + "ALT+M Switch mono / stereo mode", "TAB Cycle between editing modes", "INS Insert row (Press on endmark to", "DEL Delete row change patt. length)", @@ -340,7 +342,7 @@ void onlinehelp(int standalone,int context) sprintf(textbuffer, "%s Online Help", programname); printtext(1, 0, colors.CHEADER, textbuffer); if(standalone) { - printtext(55, 0, colors.CHEADER, "Arrows/PgUp/PgDn/Home/End scroll, ESC exits"); + printtext(84, 0, colors.CHEADER, "Arrows/PgUp/PgDn/Home/End scroll, ESC exits"); } else { printtext(61, 0, colors.CHEADER, "Arrows/PgUp/PgDn/Home/End scroll, F12 toggles context, others exit"); } @@ -400,8 +402,8 @@ void onlinehelp(int standalone,int context) break; } - if ((mouseb) && (mousey == 1)) hview++; - if ((mouseb) && (mousey == MAX_ROWS-1)) hview--; + if ((mouseb) && (mousey >= 1) && (mousey < ((MAX_ROWS-1) / 2))) hview++; + if ((mouseb) && (mousey > ((MAX_ROWS-1) / 2) && (mousey <= MAX_ROWS-1))) hview--; if (hview > -1) hview = -1; if (hview < -(lastrow-MAX_ROWS+1)) hview = -(lastrow-MAX_ROWS+1); diff --git a/src/goattrk2.c b/src/goattrk2.c index b030f9e..3e18548 100644 --- a/src/goattrk2.c +++ b/src/goattrk2.c @@ -1211,8 +1211,6 @@ void generalcommands(void) case KEY_M: if (altpressed) { - key = 0; - rawkey = 0; switchMode(); } break; @@ -1748,17 +1746,31 @@ void readscalatuningfile() void switchMode(void) { + char nextMode[7]; + char textbuffer[80]; + + if (numsids == 1) + { + strcpy(nextMode, "STEREO"); + } + else + { + strcpy(nextMode, "MONO"); + } + + sprintf(textbuffer, "Switch to %s Mode (y/n) ?", nextMode); + printtextcp( dpos.statusBottomX+29, dpos.statusBottomY, colors.CTITLE, - "Switch mono / stereo mode (y/n)?" + textbuffer ); printtextcp( dpos.statusBottomX+29, dpos.statusBottomY+1, colors.CEDIT, - "!!!Songdata will be cleared!!!" + "!!! SONGDATA WILL BE LOST !!!" ); waitkey(); @@ -1768,11 +1780,8 @@ void switchMode(void) if ((key == 'y') || (key == 'Y')) { - printf("switchMode: yes\n"); - memset(songfilename, 0, sizeof songfilename); - // SDL_PauseAudio(1); numsids ^= 3; clearsong(1, 1, 1, 1, 1); From 44de0340be8a90dc2f923be99e72ea15162ee94c Mon Sep 17 00:00:00 2001 From: Leandro Nini Date: Sun, 5 Jul 2026 17:47:30 +0200 Subject: [PATCH 10/15] Fix --- src/goattrk2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/goattrk2.c b/src/goattrk2.c index 3e18548..223971c 100644 --- a/src/goattrk2.c +++ b/src/goattrk2.c @@ -194,9 +194,9 @@ int main(int argc, char **argv) getparam(configfile, &residdelay); getparam(configfile, &customclockrate); getparam(configfile, (unsigned*)&win_fullscreen); - getparam(configfile, &combwaves); getfloatparam(configfile, &basepitch); getfloatparam(configfile, &filterbias); + getparam(configfile, &combwaves); getfloatparam(configfile, &equaldivisionsperoctave); getstringparam(configfile, specialnotenames); getstringparam(configfile, scalatuningfilepath); From 2b30f6078dceb9aa8d348ad0529aa8776ccf5469 Mon Sep 17 00:00:00 2001 From: Leandro Nini Date: Sun, 5 Jul 2026 18:03:40 +0200 Subject: [PATCH 11/15] Fix --- src/bme/bme_win.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bme/bme_win.c b/src/bme/bme_win.c index 4237f0b..43bba95 100644 --- a/src/bme/bme_win.c +++ b/src/bme/bme_win.c @@ -54,7 +54,8 @@ static int win_activateclick = 0; int win_openwindow(unsigned xsize, unsigned ysize, char *appname, char *icon) { - Uint32 flags = win_fullscreen ? SDL_WINDOW_FULLSCREEN : 0; + Uint32 flags = SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_RESIZABLE; + if (win_fullscreen) flags |= SDL_WINDOW_FULLSCREEN; if (!win_windowinitted) { From be4f600b859f7089ed8ad5d474b644c666519135 Mon Sep 17 00:00:00 2001 From: Leandro Nini Date: Sun, 5 Jul 2026 19:00:10 +0200 Subject: [PATCH 12/15] Fixes --- src/gplay.c | 6 ------ src/greloc.c | 4 ++-- src/gsound.c | 23 ----------------------- src/gsound.h | 2 -- 4 files changed, 2 insertions(+), 33 deletions(-) diff --git a/src/gplay.c b/src/gplay.c index 7b64831..da357ef 100644 --- a/src/gplay.c +++ b/src/gplay.c @@ -89,31 +89,25 @@ void initchannels(void) void initsong(int num, int mode) { - sound_suspend(); songinit = PLAY_STOPPED; psnum = num; songinit = mode; startpattpos = 0; - sound_flush(); } void initsongpos(int num, int mode, int pattpos) { - sound_suspend(); songinit = PLAY_STOPPED; psnum = num; songinit = mode; startpattpos = pattpos; - sound_flush(); } void stopsong(void) { if (songinit != PLAY_STOPPED) { - sound_suspend(); songinit = PLAY_STOP; - sound_flush(); } } diff --git a/src/greloc.c b/src/greloc.c index 63f076a..9827a5e 100644 --- a/src/greloc.c +++ b/src/greloc.c @@ -2238,7 +2238,7 @@ void relocator_stereo(void) memset(pattused, 0, sizeof pattused); memset(instrused, 0, sizeof instrused); - memset(chnused, 0, sizeof chnused); + memset(chnused_stereo, 0, sizeof chnused_stereo); memset(tableused, 0, sizeof tableused); memset(tablemap, 0, sizeof tablemap); tableerror = 0; @@ -2270,7 +2270,7 @@ void relocator_stereo(void) for (f = 0; f < pattlen[num]; f++) { if ((pattern[num][f*4] != REST) || (pattern[num][f*4+1]) || (pattern[num][f*4+2])) - chnused[d] = 1; + chnused_stereo[d] = 1; } } else diff --git a/src/gsound.c b/src/gsound.c index 73bf3f2..846fd8c 100644 --- a/src/gsound.c +++ b/src/gsound.c @@ -38,11 +38,6 @@ int sound_init(unsigned mr, unsigned writer, unsigned m, unsigned ntsc, unsigned multiplier, unsigned interpolate, unsigned customclockrate, unsigned exsid, float filterbias, unsigned combwaves) { -#ifdef __WIN32__ - if (!flushmutex) - flushmutex = SDL_CreateMutex(); -#endif - sound_uninit(); if (multiplier) @@ -217,24 +212,6 @@ void sound_uninit(void) #endif } -void sound_suspend(void) -{ - #ifdef __WIN32__ - SDL_LockMutex(flushmutex); - suspendplayroutine = TRUE; - SDL_UnlockMutex(flushmutex); - #endif -} - -void sound_flush(void) -{ - #ifdef __WIN32__ - SDL_LockMutex(flushmutex); - flushplayerthread = TRUE; - SDL_UnlockMutex(flushmutex); - #endif -} - Uint32 sound_timer(void *userdata, SDL_TimerID timerID, Uint32 interval) { if (!initted) return interval; diff --git a/src/gsound.h b/src/gsound.h index ce61cc4..6705881 100644 --- a/src/gsound.h +++ b/src/gsound.h @@ -16,7 +16,5 @@ int sound_init(unsigned mr, unsigned writer, unsigned m, unsigned ntsc, unsigned multiplier, unsigned interpolate, unsigned customclockrate, unsigned exsid, float filterbias, unsigned combwaves); void sound_uninit(void); -void sound_suspend(void); -void sound_flush(void); #endif From c19bf3ca45fd83d1e736fee6c42d9ee031176c81 Mon Sep 17 00:00:00 2001 From: Leandro Nini Date: Sun, 5 Jul 2026 20:10:17 +0200 Subject: [PATCH 13/15] Fix --- src/gsound.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/gsound.c b/src/gsound.c index 846fd8c..4a5836c 100644 --- a/src/gsound.c +++ b/src/gsound.c @@ -147,20 +147,7 @@ void sound_uninit(void) if (useexsid) { -#ifdef __WIN32__ - if (!playerthread) - { - SDL_RemoveTimer(timer); - } - else - { - runplayerthread = FALSE; - SDL_WaitThread(playerthread, NULL); - playerthread = NULL; - } -#else SDL_RemoveTimer(timer); -#endif } else { From 781c5ff794b17fec2b47341bd5b626d59b0ee041 Mon Sep 17 00:00:00 2001 From: Leandro Nini Date: Sun, 5 Jul 2026 20:41:16 +0200 Subject: [PATCH 14/15] More changes from gt2fork --- src/bme/bme_joy.h | 4 ---- src/bme/bme_win.c | 6 ------ src/bme/bme_win.h | 1 - src/gconsole.c | 4 +++- src/gdisplay.c | 8 +++++--- src/gfile.c | 8 +++++--- src/ghelp.c | 8 +++++--- src/ginstr.c | 8 +++++--- src/goattrk2.c | 11 ++++++++++- src/gorder.c | 8 +++++--- src/gpattern.c | 18 ++++++++++++++---- src/gplay.c | 8 +++++--- src/greloc.c | 15 ++++++++++----- src/gsid.cpp | 4 +++- src/gsong.c | 8 +++++--- src/gsound.c | 8 +++++--- src/gtable.c | 8 +++++--- 17 files changed, 85 insertions(+), 50 deletions(-) delete mode 100644 src/bme/bme_joy.h diff --git a/src/bme/bme_joy.h b/src/bme/bme_joy.h deleted file mode 100644 index 0962454..0000000 --- a/src/bme/bme_joy.h +++ /dev/null @@ -1,4 +0,0 @@ -// Joystick functions header file - -int joy_detect(unsigned id); -unsigned joy_getstatus(unsigned id, int threshold); diff --git a/src/bme/bme_win.c b/src/bme/bme_win.c index 43bba95..caf0cbe 100644 --- a/src/bme/bme_win.c +++ b/src/bme/bme_win.c @@ -24,7 +24,6 @@ SDL_Window *win_window = NULL; int win_openwindow(unsigned xsize, unsigned ysize, char *appname, char *icon); void win_closewindow(void); -void win_messagebox(char *string); void win_checkmessages(void); int win_getspeed(int framerate); void win_setmousemode(int mode); @@ -84,11 +83,6 @@ void win_closewindow(void) SDL_DestroyWindow(win_window); } -void win_messagebox(char *string) -{ - return; -} - int win_getspeed(int framerate) { // Note: here 1/10000th of a second accuracy is used (although diff --git a/src/bme/bme_win.h b/src/bme/bme_win.h index f7069cc..5aa7202 100644 --- a/src/bme/bme_win.h +++ b/src/bme/bme_win.h @@ -2,7 +2,6 @@ int win_openwindow(unsigned xsize, unsigned ysize, char *appname, char *icon); void win_closewindow(void); -void win_messagebox(char *string); void win_checkmessages(void); int win_getspeed(int framerate); void win_setmousemode(int mode); diff --git a/src/gconsole.c b/src/gconsole.c index 56372bf..4d7ae39 100644 --- a/src/gconsole.c +++ b/src/gconsole.c @@ -1,5 +1,7 @@ /* - * GOATTRACKER "console" output routines + * ============================================================================= + * "console" output routines + * ============================================================================= */ #define GCONSOLE_C diff --git a/src/gdisplay.c b/src/gdisplay.c index 9f33875..84d3058 100644 --- a/src/gdisplay.c +++ b/src/gdisplay.c @@ -1,6 +1,8 @@ -// -// GOATTRACKER v2 screen display routines -// +/* + * ============================================================================= + * screen display routines + * ============================================================================= + */ #define GDISPLAY_C diff --git a/src/gfile.c b/src/gfile.c index d54fb3c..88ff13a 100644 --- a/src/gfile.c +++ b/src/gfile.c @@ -1,6 +1,8 @@ -// -// GOATTRACKER v2 file selector -// +/* + * ============================================================================= + * file selector + * ============================================================================= + */ #define GFILE_C diff --git a/src/ghelp.c b/src/ghelp.c index fe0ad3c..126f143 100644 --- a/src/ghelp.c +++ b/src/ghelp.c @@ -1,6 +1,8 @@ -// -// GOATTRACKER v2 online help -// +/* + * ============================================================================= + * online help + * ============================================================================= + */ #define GHELP_C diff --git a/src/ginstr.c b/src/ginstr.c index 9fa46f6..ec6034b 100644 --- a/src/ginstr.c +++ b/src/ginstr.c @@ -1,6 +1,8 @@ -// -// GOATTRACKER v2 instrument editor -// +/* + * ============================================================================= + * instrument editor + * ============================================================================= + */ #define GINSTR_C diff --git a/src/goattrk2.c b/src/goattrk2.c index 223971c..cdeebf9 100644 --- a/src/goattrk2.c +++ b/src/goattrk2.c @@ -1146,7 +1146,16 @@ void generalcommands(void) if (shiftpressed) mutechannel(epchn); else - stopsong(); + { + if (isplaying()) + { + stopsong(); + } + else + { + releasenote(epchn); + } + } break; case KEY_F5: diff --git a/src/gorder.c b/src/gorder.c index 2254bd7..e9eced3 100644 --- a/src/gorder.c +++ b/src/gorder.c @@ -1,6 +1,8 @@ -// -// GOATTRACKER v2 orderlist & songname editor -// +/* + * ============================================================================= + * orderlist & songname editor + * ============================================================================= + */ #define GORDER_C diff --git a/src/gpattern.c b/src/gpattern.c index e5fa31f..a6fe66f 100644 --- a/src/gpattern.c +++ b/src/gpattern.c @@ -1,6 +1,8 @@ -// -// GOATTRACKER v2 pattern editor -// +/* + * ============================================================================= + * pattern editor + * ============================================================================= + */ #define GPATTERN_C @@ -144,7 +146,7 @@ void patterncommands(void) if (newnote > LASTNOTE) newnote = -1; if ((rawkey == KEY_BACKSPACE) && (!epcolumn)) newnote = REST; - if ((rawkey == 0x14) && (!epcolumn)) newnote = KEYOFF; + if ((rawkey == KEY_CAPSLOCK) && (!epcolumn)) newnote = KEYOFF; if (rawkey == KEY_ENTER) { switch(epcolumn) @@ -994,6 +996,14 @@ void patterncommands(void) if (shiftpressed) mutechannel(rawkey - KEY_1); break; + case KEY_4: + case KEY_5: + case KEY_6: + if (shiftpressed && (numsids == 2)) + { + mutechannel(rawkey - KEY_1); + } + break; } if ((keypreset == KEY_DMC) && (hexnybble >= 0) && (hexnybble <= 7) && (!epcolumn)) { diff --git a/src/gplay.c b/src/gplay.c index da357ef..cd4ffe6 100644 --- a/src/gplay.c +++ b/src/gplay.c @@ -1,6 +1,8 @@ -// -// GOATTRACKER v2 playroutine -// +/* + * ============================================================================= + * playroutine + * ============================================================================= + */ #define GPLAY_C diff --git a/src/greloc.c b/src/greloc.c index 9827a5e..3c97aab 100644 --- a/src/greloc.c +++ b/src/greloc.c @@ -1,6 +1,8 @@ -// -// LoadTracker packer/relocator -// +/* + * ============================================================================= + * packer/relocator + * ============================================================================= + */ #define GRELOC_C @@ -41,10 +43,13 @@ unsigned char tableused[MAX_TABLES][MAX_TABLELEN+1]; unsigned char tablemap[MAX_TABLES][MAX_TABLELEN+1]; int pattoffset[MAX_PATT]; int pattsize[MAX_PATT]; -int songoffset[MAX_SONGS][MAX_CHN_MONO]; -int songsize[MAX_SONGS][MAX_CHN_MONO]; +/* songoffset and songsize work also in mono mode with same size as stereo */ +int songoffset[MAX_SONGS][MAX_CHN]; +int songsize[MAX_SONGS][MAX_CHN]; +/* so those two aren't needed when combining the relocator code */ int songoffset_stereo[MAX_SONGS][MAX_CHN]; int songsize_stereo[MAX_SONGS][MAX_CHN]; + int tableerror; int channels; int fixedparams; diff --git a/src/gsid.cpp b/src/gsid.cpp index 34f1a7e..02aa6a1 100644 --- a/src/gsid.cpp +++ b/src/gsid.cpp @@ -1,5 +1,7 @@ /* - * GOATTRACKER reSID interface + * ============================================================================= + * reSIDfp interface + * ============================================================================= */ #define GSID_C diff --git a/src/gsong.c b/src/gsong.c index da35d11..2c2c911 100644 --- a/src/gsong.c +++ b/src/gsong.c @@ -1,6 +1,8 @@ -// -// GOATTRACKER v2 song data model, loading/saving/conversion -// +/* + * ============================================================================= + * song data model, loading/saving/conversion + * ============================================================================= + */ #define GSONG_C diff --git a/src/gsound.c b/src/gsound.c index 4a5836c..93b252e 100644 --- a/src/gsound.c +++ b/src/gsound.c @@ -1,6 +1,8 @@ -// -// GOATTRACKER sound routines -// +/* + * ============================================================================= + * sound routines + * ============================================================================= + */ #define GSOUND_C diff --git a/src/gtable.c b/src/gtable.c index d5d4979..2f37d2d 100644 --- a/src/gtable.c +++ b/src/gtable.c @@ -1,6 +1,8 @@ -// -// GOATTRACKER v2 table editor -// +/* + * ============================================================================= + * table editor + * ============================================================================= + */ #define GTABLE_C From e522d31425dd3ca04d8aba3a5c95102809ce4922 Mon Sep 17 00:00:00 2001 From: Leandro Nini Date: Sun, 5 Jul 2026 20:53:59 +0200 Subject: [PATCH 15/15] Apply more changes from gt2fork https://github.com/jansalleine/gt2fork/commit/02b2daf46b7769da24620a5088b6cc7cc32f6a8a https://github.com/jansalleine/gt2fork/commit/a59dc994f264e754435fb3865b445af5082573c2 https://github.com/jansalleine/gt2fork/commit/b742f342613c1a02c24859be7f4ed1260876d548 --- src/altplayer.s | 6 ++++ src/altplayer_s.s | 6 ++++ src/gdisplay.c | 10 +++++- src/goattrk2.c | 84 +++++++++++++++++++++++++++++++++++++++++++++-- src/goattrk2.h | 2 ++ src/greloc.c | 23 +++++++++++-- src/player.s | 6 ++++ src/player_s.s | 6 ++++ 8 files changed, 137 insertions(+), 6 deletions(-) diff --git a/src/altplayer.s b/src/altplayer.s index 2b3a9d6..f86eff5 100644 --- a/src/altplayer.s +++ b/src/altplayer.s @@ -520,6 +520,12 @@ mt_init: adc #$00 .ENDIF sta mt_initsongnum+1 + .IF (CIAVALHI != 0) + lda #CIAVALLO + sta $dc04 + lda #CIAVALHI + sta $dc05 + .ENDIF rts ;Play soundeffect -routine diff --git a/src/altplayer_s.s b/src/altplayer_s.s index 2d7f4b6..910c8ae 100644 --- a/src/altplayer_s.s +++ b/src/altplayer_s.s @@ -505,6 +505,12 @@ mt_init: adc #$00 .ENDIF sta mt_initsongnum+1 + .IF (CIAVALHI != 0) + lda #CIAVALLO + sta $dc04 + lda #CIAVALHI + sta $dc05 + .ENDIF rts ;Play soundeffect -routine diff --git a/src/gdisplay.c b/src/gdisplay.c index 84d3058..790f45f 100644 --- a/src/gdisplay.c +++ b/src/gdisplay.c @@ -110,7 +110,7 @@ void printstatus(void) sprintf(textbuffer, "HR:%04X", adparam); printtext(dpos.statusTopFvX+19, dpos.statusTopY, colors.CHEADER, textbuffer); - if (eamode) printbg(dpos.statusTopFvX+22+eacolumn, dpos.statusTopY, cc, 1); + if (eamode && !ebmode) printbg(dpos.statusTopFvX+22+eacolumn, dpos.statusTopY, cc, 1); if (multiplier) { @@ -119,6 +119,14 @@ void printstatus(void) } else printtext(dpos.statusTopFvX+27, dpos.statusTopY, colors.CHEADER, "25Hz"); + if (multiplier == 1) + { + sprintf(textbuffer, "%03dBPM", snd_bpmtempo); + printtext(dpos.statusTopFvX+31, dpos.statusTopY, colors.CHEADER, textbuffer); + + if (eamode && ebmode) printbg(dpos.statusTopFvX+31+eacolumn, dpos.statusTopY, cc, 1); + } + printtext(dpos.statusTopEndX-8, dpos.statusTopY, colors.CHEADER, "F12=HELP"); } else diff --git a/src/goattrk2.c b/src/goattrk2.c index cdeebf9..9631cc2 100644 --- a/src/goattrk2.c +++ b/src/goattrk2.c @@ -40,6 +40,7 @@ int cursorcolortable[] = {1,2,7,2}; int exitprogram = 0; int eacolumn = 0; int eamode = 0; +int ebmode = 0; unsigned keypreset = KEY_TRACKER; unsigned playerversion = 0; @@ -937,6 +938,8 @@ void mousecommands(void) (mousex <= dpos.statusTopFvX+28)) prevmultiplier(); if ((mousex >= dpos.statusTopFvX+29) && (mousex <= dpos.statusTopFvX+30)) nextmultiplier(); + if ((mousex >= dpos.statusTopFvX+31) && + (mousex <= dpos.statusTopFvX+33)) editbpm(); if ((mousex >= dpos.statusTopEndX-8) && (mousex <= dpos.statusTopEndX-1)) onlinehelp(0,0); } @@ -1494,6 +1497,81 @@ void editadsr(void) } } +void editbpm(void) +{ + eamode = 1; + ebmode = 1; + eacolumn = 0; + + for (;;) + { + waitkeymouse(); + + if (win_quitted) + { + exitprogram = 1; + key = 0; + rawkey = 0; + return; + } + + if (key >= 48 && key <= 58) + { + int number = key - 48; + int tempnum = 0; + + switch(eacolumn) + { + case 0: + snd_bpmtempo = snd_bpmtempo - (((snd_bpmtempo / 100) % 10) * 100) + (number * 100); + break; + + case 1: + snd_bpmtempo = snd_bpmtempo - (((snd_bpmtempo / 10) % 10) * 10) + (number * 10); + break; + + case 2: + snd_bpmtempo = snd_bpmtempo - (((snd_bpmtempo / 1) % 10) * 1) + (number * 1); + break; + } + eacolumn++; + } + + switch(rawkey) + { + case KEY_F7: + if (!shiftpressed) break; + + case KEY_ESC: + case KEY_ENTER: + case KEY_TAB: + eamode = 0; + ebmode = 0; + key = 0; + rawkey = 0; + return; + + case KEY_BACKSPACE: + if (!eacolumn) break; + case KEY_LEFT: + eacolumn--; + break; + + case KEY_RIGHT: + eacolumn++; + } + eacolumn &= 3; + if (eacolumn == 3) eacolumn = 0; + + if ((mouseb) && (!prevmouseb)) + { + eamode = 0; + ebmode = 0; + return; + } + } +} + void getparam(FILE *handle, unsigned *value) { char *configptr; @@ -1574,7 +1652,7 @@ void getstringparam(FILE *handle, char *value) } configptr = configbuf; - + sscanf(configptr, "%s", value); } @@ -1693,7 +1771,7 @@ void readscalatuningfile() } configptr = configbuf; sscanf(configptr, "%63[^\t\n]", tuningname); - + // Tuning count for (;;) { @@ -1703,7 +1781,7 @@ void readscalatuningfile() } configptr = configbuf; sscanf(configptr, "%d", &tuningcount); - + // Tunings for (i = 0; i < tuningcount; i++) { diff --git a/src/goattrk2.h b/src/goattrk2.h index bbce2bd..4e85b25 100644 --- a/src/goattrk2.h +++ b/src/goattrk2.h @@ -56,6 +56,7 @@ extern int cursorcolortable[]; extern int exitprogram; extern int eacolumn; extern int eamode; +extern int ebmode; extern unsigned keypreset; extern unsigned playerversion; extern int fileformat; @@ -117,6 +118,7 @@ void clear(void); void prevmultiplier(void); void nextmultiplier(void); void editadsr(void); +void editbpm(void); void calculatefreqtable(void); void setspecialnotenames(void); void readscalatuningfile(void); diff --git a/src/greloc.c b/src/greloc.c index 3c97aab..fda85b9 100644 --- a/src/greloc.c +++ b/src/greloc.c @@ -88,6 +88,8 @@ int nocalculatedspeed; int nonormalspeed; int nozerospeed; +int ciaval; + struct membuf src = STATIC_MEMBUF_INIT; struct membuf dest = STATIC_MEMBUF_INIT; @@ -518,8 +520,21 @@ void relocator(void) else sprintf(textbuffer, "%s Packer/Relocator - %s", programname, loadedsongfilename); textbuffer[MAX_COLUMNS] = 0; - printtext(0, 0, colors.CHEADER, textbuffer); + printtext(1, 0, colors.CHEADER, textbuffer); printtext(1, 2, colors.CTITLE, "SELECT PLAYROUTINE OPTIONS: (CURSORS=MOVE/CHANGE, ENTER=ACCEPT, ESC=CANCEL)"); + + if (multiplier == 1 && snd_bpmtempo != 125) + { + ciaval = 19566 - ((19655 / 125) * (snd_bpmtempo - 125)); + + sprintf(textbuffer, "[INFO] CIA timer value for %03d BPM: $%04X", snd_bpmtempo, ciaval); + printtext(1, 3+MAX_OPTIONS+8, colors.CEDIT, textbuffer); + } + else + { + ciaval = 0; + } + selectdone = 0; while (!selectdone) { @@ -1130,6 +1145,8 @@ void relocator(void) insertdefine("NUMLEGATOINSTR", numlegato); insertdefine("ADPARAM", adparam >> 8); insertdefine("SRPARAM", adparam & 0xff); + insertdefine("CIAVALLO", ciaval & 0xff); + insertdefine("CIAVALHI", ciaval >> 8); if ((instr[MAX_INSTR-1].ad >= 2) && (!(instr[MAX_INSTR-1].ptr[WTBL]))) insertdefine("DEFAULTTEMPO", instr[MAX_INSTR-1].ad - 1); else @@ -1625,7 +1642,7 @@ void relocator(void) // Song speed bits byte = 0x00; - if ((ntsc) || (multiplier > 1) || (!multiplier)) byte = 0xff; + if ((ntsc) || (multiplier > 1) || (!multiplier) || (ciaval)) byte = 0xff; fwrite8(songhandle, byte); fwrite8(songhandle, byte); fwrite8(songhandle, byte); @@ -3182,6 +3199,8 @@ void relocator_stereo(void) insertdefine("NUMLEGATOINSTR", numlegato); insertdefine("ADPARAM", adparam >> 8); insertdefine("SRPARAM", adparam & 0xff); + insertdefine("CIAVALLO", ciaval & 0xff); + insertdefine("CIAVALHI", ciaval >> 8); if ((instr[MAX_INSTR-1].ad >= 2) && (!(instr[MAX_INSTR-1].ptr[WTBL]))) insertdefine("DEFAULTTEMPO", instr[MAX_INSTR-1].ad - 1); else diff --git a/src/player.s b/src/player.s index f061bd4..78cadca 100644 --- a/src/player.s +++ b/src/player.s @@ -520,6 +520,12 @@ mt_init: adc #$00 .ENDIF sta mt_initsongnum+1 + .IF (CIAVALHI != 0) + lda #CIAVALLO + sta $dc04 + lda #CIAVALHI + sta $dc05 + .ENDIF rts ;Play soundeffect -routine diff --git a/src/player_s.s b/src/player_s.s index 1bae006..e51dd80 100644 --- a/src/player_s.s +++ b/src/player_s.s @@ -505,6 +505,12 @@ mt_init: adc #$00 .ENDIF sta mt_initsongnum+1 + .IF (CIAVALHI != 0) + lda #CIAVALLO + sta $dc04 + lda #CIAVALHI + sta $dc05 + .ENDIF rts ;Play soundeffect -routine