home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 15 / CD_ASCQ_15_070894.iso / vrac / mikmod43.zip / MODPLAY.C < prev    next >
C/C++ Source or Header  |  1994-04-30  |  16KB  |  768 lines

  1. #include <dos.h>
  2. #include <stdlib.h>
  3. #include "mytypes.h"
  4. #include "modload.h"
  5. #include "modplay.h"
  6.  
  7. MODFILE *pf;            // <- this modfile is being played
  8. UBYTE *patptr;            // pointer to the current pattern (first row)
  9. UBYTE *rowptr;            // pointer to the current row
  10. UWORD reppos;            // patternloop position
  11. UWORD repcnt;            // times to loop
  12. UWORD patpos;            // current row
  13. UWORD sngpos;            // current song position
  14. UWORD sngspd;            // current songspeed
  15. UWORD vbtick;            // tick counter
  16. UWORD patbrk;            // patternbreak position
  17. UBYTE patdly;            // patterndelay counter
  18. UBYTE jstbrk;            // breakflag
  19. int forbid;                // forbidflag
  20.  
  21. /*
  22.     Set forbid to 1 when you want to modify any of the sngpos, patpos etc.
  23.     variables and clear it when you're done. This prevents getting strange
  24.     results due to intermediate interrupts.
  25. */
  26.  
  27.  
  28. AUDTMP mp_audio[8];        // max eight channels
  29. UBYTE  mp_bpm;            // beats-per-minute speed
  30. UBYTE  mp_mainvol=80;      // main volume 0%-100%
  31. int mp_extspdflag=1;    // extended speed flag, default enabled
  32.  
  33.  
  34. void (*PlayRout)(int chn,AUDTMP *aud,MODFILE *mf)=NULL;
  35.  
  36.  
  37. UBYTE VibratoTable[32]={
  38.     0,24,49,74,97,120,141,161,
  39.     180,197,212,224,235,244,250,253,
  40.     255,253,250,244,235,224,212,197,
  41.     180,161,141,120,97,74,49,24
  42. };
  43.  
  44.  
  45. UWORD npertab[16][60]={
  46.  
  47. // -> Tuning 0
  48.  
  49.     1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
  50.     856,808,762,720,678,640,604,570,538,508,480,453,
  51.     428,404,381,360,339,320,302,285,269,254,240,226,
  52.     214,202,190,180,170,160,151,143,135,127,120,113,
  53.     107,101,95,90,85,80,75,71,67,63,60,56,
  54.  
  55. // -> Tuning 1
  56.  
  57.     1700,1604,1514,1430,1348,1274,1202,1134,1070,1010,954,900,
  58.     850,802,757,715,674,637,601,567,535,505,477,450,
  59.     425,401,379,357,337,318,300,284,268,253,239,225,
  60.     213,201,189,179,169,159,150,142,134,126,119,113,
  61.     106,100,94,89,84,79,75,71,67,63,59,56,
  62.  
  63. // -> Tuning 2
  64.  
  65.     1688,1592,1504,1418,1340,1264,1194,1126,1064,1004,948,894,
  66.     844,796,752,709,670,632,597,563,532,502,474,447,
  67.     422,398,376,355,335,316,298,282,266,251,237,224,
  68.     211,199,188,177,167,158,149,141,133,125,118,112,
  69.     105,99,94,88,83,79,74,70,66,62,59,56,
  70.  
  71. // -> Tuning 3
  72.  
  73.     1676,1582,1492,1408,1330,1256,1184,1118,1056,996,940,888,
  74.     838,791,746,704,665,628,592,559,528,498,470,444,
  75.     419,395,373,352,332,314,296,280,264,249,235,222,
  76.     209,198,187,176,166,157,148,140,132,125,118,111,
  77.     104,99,93,88,83,78,74,70,66,62,59,55,
  78.  
  79. // -> Tuning 4
  80.  
  81.     1664,1570,1482,1398,1320,1246,1176,1110,1048,990,934,882,
  82.     832,785,741,699,660,623,588,555,524,495,467,441,
  83.     416,392,370,350,330,312,294,278,262,247,233,220,
  84.     208,196,185,175,165,156,147,139,131,124,117,110,
  85.     104,98,92,87,82,78,73,69,65,62,58,55,
  86.  
  87. // -> Tuning 5
  88.  
  89.     1652,1558,1472,1388,1310,1238,1168,1102,1040,982,926,874,
  90.     826,779,736,694,655,619,584,551,520,491,463,437,
  91.     413,390,368,347,328,309,292,276,260,245,232,219,
  92.     206,195,184,174,164,155,146,138,130,123,116,109,
  93.     103,97,92,87,82,77,73,69,65,61,58,54,
  94.  
  95. // -> Tuning 6
  96.  
  97.     1640,1548,1460,1378,1302,1228,1160,1094,1032,974,920,868,
  98.     820,774,730,689,651,614,580,547,516,487,460,434,
  99.     410,387,365,345,325,307,290,274,258,244,230,217,
  100.     205,193,183,172,163,154,145,137,129,122,115,109,
  101.     102,96,91,86,81,77,72,68,64,61,57,54,
  102.  
  103. // -> Tuning 7
  104.  
  105.     1628,1536,1450,1368,1292,1220,1150,1086,1026,968,914,862,
  106.     814,768,725,684,646,610,575,543,513,484,457,431,
  107.     407,384,363,342,323,305,288,272,256,242,228,216,
  108.     204,192,181,171,161,152,144,136,128,121,114,108,
  109.     102,96,90,85,80,76,72,68,64,60,57,54,
  110.  
  111. // -> Tuning -8
  112.  
  113.     1814,1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,
  114.     907,856,808,762,720,678,640,604,570,538,508,480,
  115.     453,428,404,381,360,339,320,302,285,269,254,240,
  116.     226,214,202,190,180,170,160,151,143,135,127,120,
  117.     113,107,101,95,90,85,80,75,71,67,63,60,
  118.  
  119. // -> Tuning -7
  120.  
  121.     1800,1700,1604,1514,1430,1350,1272,1202,1134,1070,1010,954,
  122.     900,850,802,757,715,675,636,601,567,535,505,477,
  123.     450,425,401,379,357,337,318,300,284,268,253,238,
  124.     225,212,200,189,179,169,159,150,142,134,126,119,
  125.     112,106,100,94,89,84,79,75,71,67,63,59,
  126.  
  127. // -> Tuning -6
  128.  
  129.     1788,1688,1592,1504,1418,1340,1264,1194,1126,1064,1004,948,
  130.     894,844,796,752,709,670,632,597,563,532,502,474,
  131.     447,422,398,376,355,335,316,298,282,266,251,237,
  132.     223,211,199,188,177,167,158,149,141,133,125,118,
  133.     111,105,99,94,88,83,79,74,70,66,62,59,
  134.  
  135. // -> Tuning -5
  136.  
  137.     1774,1676,1582,1492,1408,1330,1256,1184,1118,1056,996,940,
  138.     887,838,791,746,704,665,628,592,559,528,498,470,
  139.     444,419,395,373,352,332,314,296,280,264,249,235,
  140.     222,209,198,187,176,166,157,148,140,132,125,118,
  141.     111,104,99,93,88,83,78,74,70,66,62,59,
  142.  
  143. // -> Tuning -4
  144.  
  145.     1762,1664,1570,1482,1398,1320,1246,1176,1110,1048,988,934,
  146.     881,832,785,741,699,660,623,588,555,524,494,467,
  147.     441,416,392,370,350,330,312,294,278,262,247,233,
  148.     220,208,196,185,175,165,156,147,139,131,123,117,
  149.     110,104,98,92,87,82,78,73,69,65,61,58,
  150.  
  151. // -> Tuning -3
  152.  
  153.     1750,1652,1558,1472,1388,1310,1238,1168,1102,1040,982,926,
  154.     875,826,779,736,694,655,619,584,551,520,491,463,
  155.     437,413,390,368,347,328,309,292,276,260,245,232,
  156.     219,206,195,184,174,164,155,146,138,130,123,116,
  157.     109,103,97,92,87,82,77,73,69,65,61,58,
  158.  
  159. // -> Tuning -2
  160.  
  161.     1736,1640,1548,1460,1378,1302,1228,1160,1094,1032,974,920,
  162.     868,820,774,730,689,651,614,580,547,516,487,460,
  163.     434,410,387,365,345,325,307,290,274,258,244,230,
  164.     217,205,193,183,172,163,154,145,137,129,122,115,
  165.     108,102,96,91,86,81,77,72,68,64,61,57,
  166.  
  167. // -> Tuning -1
  168.  
  169.     1724,1628,1536,1450,1368,1292,1220,1150,1086,1026,968,914,
  170.     862,814,768,725,684,646,610,575,543,513,484,457,
  171.     431,407,384,363,342,323,305,288,272,256,242,228,
  172.     216,203,192,181,171,161,152,144,136,128,121,114,
  173.     108,101,96,90,85,80,76,72,68,64,60,57
  174. };
  175.  
  176.  
  177. void GetPatPtr(void)
  178. {
  179.     patpos=0;
  180.     patptr=pf->patterns[pf->positions[sngpos]];
  181. }
  182.  
  183.  
  184.  
  185. void NewPatPtr(void)
  186. {
  187.     sngpos++;
  188.     if(sngpos==pf->songlength) sngpos=0;
  189.     GetPatPtr();
  190. }
  191.  
  192.  
  193.  
  194. void DoEEffects(AUDTMP *a)
  195. {
  196.     UBYTE eff,dat,nib;
  197.  
  198.     eff=a->eff;
  199.     dat=a->dat;
  200.     nib=dat&0xf;
  201.  
  202.     switch(dat>>4){
  203.  
  204.         case 0x0:    // filter toggle, not supported
  205.                 break;
  206.  
  207.         case 0x1:    // fineslide up
  208.                 a->tmpperiod-=nib;
  209.                 eff=dat=0;    // only once
  210.                 break;
  211.  
  212.         case 0x2:    // fineslide dn
  213.                 a->tmpperiod+=nib;
  214.                 eff=dat=0;    // only once
  215.                 break;
  216.  
  217.         case 0x3:    // glissando ctrl
  218.                 a->glissando=nib;
  219.                 break;
  220.  
  221.         case 0x4:    // set vibrato waveform
  222.                 a->wavecontrol&=0xf0;
  223.                 a->wavecontrol|=nib;
  224.                 break;
  225.  
  226.         case 0x5:    // set finetune
  227.                 a->finetune=nib;
  228.                 a->tmpperiod=npertab[nib][a->note];
  229.                 eff=dat=0;
  230.                 break;
  231.  
  232.         case 0x6:    // set patternloop
  233.  
  234.                 /* hmm.. this one is a real kludge. But now it
  235.                    works. */
  236.  
  237.                 if(nib){        // set reppos or repcnt ?
  238.  
  239.                     /* set repcnt, so check if repcnt already is set,
  240.                        which means we are already looping */
  241.  
  242.                     if(repcnt>0)
  243.                         repcnt--;        // already looping, decrease counter
  244.                     else
  245.                         repcnt=nib;        // not yet looping, so set repcnt
  246.  
  247.                     if(repcnt)            // jump to reppos if repcnt>0
  248.                         patpos=reppos;
  249.                 }
  250.                 else{
  251.                     reppos=patpos-1;    // set reppos
  252.                 }
  253.  
  254.                 eff=dat=0;
  255.                 break;
  256.  
  257.         case 0x7:    // set tremolo waveform
  258.                 a->wavecontrol&=0x0f;
  259.                 a->wavecontrol|=nib<<4;
  260.                 break;
  261.  
  262.         case 0x8:    // not used
  263.                 break;
  264.  
  265.         case 0x9:    // retrig note
  266.  
  267.                 /* only retrigger if
  268.                    data nibble > 0 */
  269.  
  270.                 if(nib>0){
  271.                     if(a->retrig==0){
  272.  
  273.                         /* when retrig counter reaches 0,
  274.                            reset counter and restart the sample */
  275.  
  276.                         a->kick=1;
  277.                         a->retrig=nib;
  278.                     }
  279.                     a->retrig--; // countdown
  280.                 }
  281.                 break;
  282.  
  283.         case 0xa:    // fine volume slide up
  284.                 a->tmpvolume+=nib;
  285.                 if(a->tmpvolume>64) a->tmpvolume=64;
  286.  
  287.                 eff=dat=0;
  288.                 break;
  289.  
  290.         case 0xb:    // fine volume slide dn
  291.                 a->tmpvolume-=nib;
  292.                 if(a->tmpvolume<0) a->tmpvolume=0;
  293.  
  294.                 eff=dat=0;    // only once
  295.                 break;
  296.  
  297.         case 0xc:    // cut note
  298.  
  299.                 /* When vbtick reaches the cut-note value,
  300.                    turn the volume to zero ( Just like
  301.                    on the amiga) */
  302.  
  303.                 if(vbtick>=nib){
  304.                     a->tmpvolume=0;            // just turn the volume down
  305.                     eff=dat=0;
  306.                 }
  307.                 break;
  308.  
  309.         case 0xd:    // note delay
  310.  
  311.                 /* delay the start of the
  312.                    sample until vbtick>=nib */
  313.  
  314.                 if(vbtick>=nib){
  315.                     a->kick=1;
  316.                     eff=dat=0;
  317.                 }
  318.                 else a->kick=0;
  319.                 break;
  320.  
  321.         case 0xe:    // pattern delay
  322.                 patdly=nib;
  323.                 eff=dat=0;
  324.                 break;
  325.  
  326.         case 0xf:    // invert loop, not supported
  327.                 break;
  328.     }
  329.     a->eff=eff;
  330.     a->dat=dat;
  331. }
  332.  
  333.  
  334. void DoVibrato(AUDTMP *a)
  335. {
  336.     UBYTE q;
  337.     UWORD temp;
  338.  
  339.     q=(a->vibpos>>2)&0x1f;
  340.  
  341.     switch(a->wavecontrol&3){
  342.  
  343.         case 0:    // sine
  344.             temp=VibratoTable[q];
  345.             break;
  346.  
  347.         case 1:    // ramp down
  348.             q<<=3;
  349.             if(a->vibpos<0) q=255-q;
  350.             temp=q;
  351.             break;
  352.  
  353.         case 2:    // square wave
  354.             temp=255;
  355.             break;
  356.     }
  357.  
  358.     temp*=a->vibdepth;
  359.     temp>>=7;
  360.  
  361.     if(a->vibpos>=0)
  362.         a->period=a->tmpperiod+temp;
  363.     else
  364.         a->period=a->tmpperiod-temp;
  365.  
  366.     if(vbtick) a->vibpos+=a->vibspd;    // do not update when vbtick==0
  367. }
  368.  
  369.  
  370.  
  371. void DoTremolo(AUDTMP *a)
  372. {
  373.     UBYTE q;
  374.     UWORD temp;
  375.  
  376.     q=(a->trmpos>>2)&0x1f;
  377.  
  378.     switch((a->wavecontrol>>4)&3){
  379.  
  380.         case 0:    // sine
  381.             temp=VibratoTable[q];
  382.             break;
  383.  
  384.         case 1:    // ramp down
  385.             q<<=3;
  386.             if(a->trmpos<0)    q=255-q;
  387.             temp=q;
  388.             break;
  389.  
  390.         case 2:    // square wave
  391.             temp=255;
  392.             break;
  393.     }
  394.  
  395.     temp*=a->trmdepth;
  396.     temp>>=6;
  397.  
  398.     if(a->trmpos>=0){
  399.         a->volume=a->tmpvolume+temp;
  400.         if(a->volume>64) a->volume=64;
  401.     }
  402.     else{
  403.         a->volume=a->tmpvolume-temp;
  404.         if(a->volume<0) a->volume=0;
  405.     }
  406.  
  407.     if(vbtick) a->trmpos+=a->trmspd;    // do not update when vbtick==0
  408. }
  409.  
  410.  
  411. void DoVolSlide(AUDTMP *a)
  412. {
  413.     if(!vbtick) return;        // do not update when vbtick==0
  414.  
  415.     a->tmpvolume+=(a->dat>>4);            // volume slide
  416.     a->tmpvolume-=(a->dat&0xf);
  417.     if(a->tmpvolume<0) a->tmpvolume=0;
  418.     if(a->tmpvolume>64) a->tmpvolume=64;
  419. }
  420.  
  421.  
  422. void DoToneSlide(AUDTMP *a)
  423. {
  424.     int dist,t;
  425.  
  426.     if(!vbtick){        // do not update when vbtick==0
  427.         a->period=a->tmpperiod;
  428.         return;
  429.     }
  430.  
  431.     /* We have to slide a->tmpperiod towards a->wantedperiod, so
  432.        compute the difference between those two values */
  433.  
  434.     dist=a->tmpperiod-a->wantedperiod;
  435.  
  436.     if( dist==0 ||                   // if they are equal
  437.         a->portspeed>abs(dist) ){    // or if portamentospeed is too big
  438.  
  439.         a->tmpperiod=a->wantedperiod;    // make tmpperiod equal tperiod
  440.     }
  441.     else if(dist>0){                // dist>0 ?
  442.         a->tmpperiod-=a->portspeed;    // then slide up
  443.     }
  444.     else
  445.         a->tmpperiod+=a->portspeed;    // dist<0 -> slide down
  446.  
  447.     if(a->glissando){
  448.  
  449.         /* If glissando is on, find the nearest
  450.            halfnote to a->tmpperiod */
  451.  
  452.         for(t=0;t<60;t++){
  453.             if(a->tmpperiod>=npertab[a->finetune][t]) break;
  454.         }
  455.  
  456.         a->period=npertab[a->finetune][t];
  457.     }
  458.     else
  459.         a->period=a->tmpperiod;
  460. }
  461.  
  462.  
  463. void DoEffect(AUDTMP *a)
  464. {
  465.     UBYTE eff,dat,note;
  466.     WORD temp,hi,lo,arp=0;
  467.  
  468.     eff=a->eff;
  469.     dat=a->dat;
  470.     note=a->note;
  471.  
  472.     switch(eff){
  473.         case 0x0:    // arpeggio
  474.                 if(dat!=0){
  475.                     switch(vbtick%3){
  476.                         case 1:
  477.                             note+=(dat>>4); break;
  478.                         case 2:
  479.                             note+=(dat&0xf); break;
  480.                     }
  481.                     a->period=npertab[a->finetune&0xf][note];
  482.                     arp=1;        // <-- v0.42 bugfix
  483.                 }
  484.                 break;
  485.  
  486.         case 0x1:    // portamento up
  487.                 if(vbtick) a->tmpperiod-=dat;
  488.                 break;
  489.  
  490.         case 0x2:    // portamento dn
  491.                 if(vbtick) a->tmpperiod+=dat;
  492.                 break;
  493.  
  494.         case 0x3:    // toneportamento (toneslide)
  495.                 if(dat!=0) a->portspeed=dat;
  496.                 DoToneSlide(a);
  497.                 break;
  498.  
  499.         case 0x4:    // vibrato
  500.                 if(dat&0x0f) a->vibdepth=dat&0xf;
  501.                 if(dat&0xf0) a->vibspd=(dat&0xf0)>>2;
  502.                 dat=0;
  503.                 DoVibrato(a);
  504.                 break;
  505.  
  506.         case 0x5:    // tone+volume slide
  507.                 DoToneSlide(a);
  508.                 DoVolSlide(a);
  509.                 break;
  510.  
  511.         case 0x6:    // vibrato + volslide
  512.                 DoVibrato(a);
  513.                 DoVolSlide(a);
  514.                 break;
  515.  
  516.         case 0x7:    // tremolo
  517.                 if(dat&0x0f) a->trmdepth=dat&0xf;
  518.                 if(dat&0xf0) a->trmspd=(dat&0xf0)>>2;
  519.                 dat=0;
  520.                 DoTremolo(a);
  521.                 break;
  522.  
  523.         case 0x8:    // unused
  524.                 break;
  525.  
  526.         case 0x9:    // set sampleoffset
  527.                 a->start=(ULONG)dat<<8;
  528.                 if(a->start>a->size) a->start=a->size;
  529.                 eff=dat=0;
  530.                 break;
  531.  
  532.         case 0xa:   // volume slide
  533.                 DoVolSlide(a);
  534.                 break;
  535.  
  536.         case 0xb:    // position jump
  537.                 sngpos=dat;
  538.                 if(sngpos>=pf->songlength) sngpos=0;
  539.                 GetPatPtr();
  540.                 eff=dat=0;
  541.                 break;
  542.  
  543.         case 0xc:    // set volume
  544.                 a->tmpvolume=dat;
  545.                 if(a->tmpvolume>64) a->tmpvolume=64;
  546.                 else if(a->tmpvolume<0) a->tmpvolume=0;
  547.  
  548.                 eff=dat=0;
  549.                 break;
  550.  
  551.         case 0xd:    // patternbreak
  552.                 if(!jstbrk){                    // ignore when jstbrk==true
  553.                     hi=(dat&0xf0)>>4;
  554.                     lo=(dat&0xf);
  555.                     patbrk=(hi*10)+lo+1;
  556.                     if(patbrk>64) patbrk=64;    // <- v0.42 fix
  557.                 }
  558.                 eff=dat=0;
  559.                 break;
  560.  
  561.         case 0xe:    // extended effects
  562.                 DoEEffects(a);
  563.                 eff=a->eff;
  564.                 dat=a->dat;
  565.                 break;
  566.  
  567.         case 0xf:    // set speed
  568.                 if(mp_extspdflag && dat>=0x20){
  569.                     mp_bpm=dat;
  570.                 }
  571.                 else{
  572.                     sngspd=dat;
  573.                 }
  574.                 eff=dat=0;
  575.                 break;
  576.  
  577.     }
  578.     a->eff=eff;
  579.     a->dat=dat;
  580.  
  581.     // Effects 0,3,4,5,6 set period themselves
  582.  
  583.     if( !arp && (eff<0x3 || eff>0x6) ) a->period=a->tmpperiod;
  584.  
  585.     // Effect 7 sets volume itself
  586.  
  587.     if(eff!=0x7) a->volume=a->tmpvolume;
  588. }
  589.  
  590.  
  591.  
  592. void PlayNote(UBYTE *p,AUDTMP *aud)
  593. {
  594.     UWORD period;
  595.     UBYTE inst,note;
  596.  
  597.     inst=((p[0]&0xc0)>>2)|((p[1]&0xf0)>>4);
  598.     note=p[0]&0x3f;
  599.  
  600.     aud->eff=p[1]&0xf;
  601.     aud->dat=p[2];
  602.  
  603.     if(inst!=0){            // instrument change ?
  604.         inst--;                // yes, so put all instrument values into aud
  605.         aud->sample=inst;
  606.         aud->handle=pf->samples[inst].handle;
  607.         aud->tmpvolume=pf->samples[inst].volume;
  608.         aud->size=pf->samples[inst].length;
  609.         aud->finetune=pf->samples[inst].finetune;
  610.         aud->retrig=0;
  611.     }
  612.     else inst=aud->sample;    // no inst change, so use last instrument
  613.  
  614.     // enable loop if neccesary
  615.  
  616.     if(pf->samples[inst].replen>2){
  617.         aud->size=pf->samples[inst].reppos+pf->samples[inst].replen;
  618.         aud->loop=pf->samples[inst].reppos;
  619.     }
  620.     else aud->loop=pf->samples[inst].length;
  621.  
  622.     if(note!=0){
  623.         note--;
  624.  
  625.         aud->note=note;
  626.         period=npertab[pf->samples[inst].finetune&0xf][note];
  627.  
  628.         aud->wantedperiod=period;
  629.  
  630.         if(aud->eff!=0x3 && aud->eff!=0x5){
  631.             aud->tmpperiod=period;
  632.             aud->kick=1;
  633.             aud->start=0;
  634.         }
  635.  
  636.         // retrig tremolo and vibrato waves ?
  637.  
  638.         if(!(aud->wavecontrol&0x80)) aud->trmpos=0;
  639.         if(!(aud->wavecontrol&0x08)) aud->vibpos=0;
  640.     }
  641. }
  642.  
  643.  
  644.  
  645.  
  646. void MP_HandleTick(void)
  647. {
  648.     int t;
  649.  
  650.     if(forbid) return;    // don't go any further when forbid is true
  651.  
  652.     if(++vbtick>=sngspd){
  653.  
  654.         // pattern delay active ? -> wait patdly*sngspd ticks
  655.  
  656.         if(patdly){
  657.             patdly--;
  658.         }
  659.         else{
  660.  
  661.             /* Do we have to get a new patternpointer ?
  662.                (when patpos reaches 64 or when
  663.                a patternbreak is active) */
  664.  
  665.             if( patpos==64 || patbrk ){
  666.  
  667.                 NewPatPtr();    // yes, get new pattern pointer
  668.  
  669.                 if(patbrk){        // if patternbreak, set new patpos
  670.                     patpos=patbrk-1;
  671.                     jstbrk=1;
  672.  
  673.                     /* By making jstbrk true, patternbreak
  674.                        commands on this row will be ignored */
  675.                 }
  676.                 else patpos=0;
  677.             }
  678.  
  679.             rowptr=&patptr[3*patpos*pf->numchn];
  680.             for(t=0;t<pf->numchn;t++){
  681.                 PlayNote(&rowptr[t*3],&mp_audio[t]);
  682.             }
  683.  
  684.             patpos++;
  685.             patbrk=0;
  686.         }
  687.         vbtick=0;
  688.     }
  689.     else jstbrk=0;
  690.  
  691.     for(t=0;t<pf->numchn;t++){
  692.         DoEffect(&mp_audio[t]);
  693.     }
  694.  
  695.     for(t=0;t<pf->numchn;t++){
  696.         if(PlayRout!=NULL) PlayRout(t,&mp_audio[t],pf);
  697.     }
  698. }
  699.  
  700.  
  701.  
  702. void MP_Init(MODFILE *m)
  703. {
  704.     int t;
  705.  
  706.     pf=m;
  707.     reppos=0;
  708.     repcnt=0;
  709.     sngpos=0;
  710.     sngspd=6;
  711.     vbtick=5;
  712.     patbrk=0;
  713.     patdly=0;
  714.     mp_bpm=125;
  715.     forbid=0;
  716.  
  717.     /* Make sure the player doesn't start with garbage: */
  718.  
  719.     for(t=0;t<pf->numchn;t++){
  720.         mp_audio[t].kick=0;
  721.         mp_audio[t].tmpvolume=0;
  722.         mp_audio[t].retrig=0;
  723.         mp_audio[t].wavecontrol=0;
  724.         mp_audio[t].glissando=0;
  725.     }
  726.  
  727.     GetPatPtr();
  728. }
  729.  
  730.  
  731.  
  732. void MP_RegisterPlayer(void (*Player)(int chn,AUDTMP *aud,MODFILE *mf))
  733. {
  734.     PlayRout=Player;
  735. }
  736.  
  737.  
  738. void MP_ExtSpd(int yesno)
  739. {
  740.     mp_extspdflag=yesno;
  741. }
  742.  
  743.  
  744. void MP_MainVol(UBYTE volume)
  745. {
  746.     mp_mainvol=(volume>100) ? 100 : volume;
  747. }
  748.  
  749.  
  750. void MP_NextPosition(void)
  751. {
  752.     forbid=1;
  753.     sngpos=(sngpos>=(pf->songlength-1)) ? 0 : sngpos+1;
  754.     GetPatPtr();
  755.     vbtick=sngspd;
  756.     forbid=0;
  757. }
  758.  
  759.  
  760. void MP_PrevPosition(void)
  761. {
  762.     forbid=1;
  763.     sngpos=(sngpos==0) ? pf->songlength-1 : sngpos-1;
  764.     GetPatPtr();
  765.     vbtick=sngspd;
  766.     forbid=0;
  767. }
  768.