#define MAXIM  0x10000
#define VBLVAL 70938
#define VBLVALNTSC 71591
#define CIAVAL 1773447
#define CIAVALNTSC 1789772

#include<stdio.h>
#include<stdlib.h>
#include<proto/exec.h>
#include<exec/memory.h>
#include<proto/dos.h>

UBYTE	ver[]="$VER: Mod2Smp V0.78 by Hali of oNION (27/1/96)\0";
UBYTE	help[]=" [7m Module to Sample V0.78 [0m   © 1995-96 by Hali of Union\n Here comes short instruction:\n   mod2smp <modulename> <samplename> <pattern>\n        <start> <stop> <volume> <pitch note> [options]\n options:\n   -f??   VBlank speed\n   -c???  CIA speed\n   -n     NTSC\n   -s     Sustain\n   -v     VBlank only\n   -r?    Resampling method (0,1)\n and example:\n   mod2smp \"df0:mod.cipa 6\" ram:kupa 0 0 15 75 C-3 -f3\n If you have any comments or suggestions write to:\n Karol Gozlinski, Stanislawowska 1/24, 05-300 Minsk Maz., Poland\n.[0m\n\0";

struct	kupa {				// user interface
	UBYTE	modstrt;
	UBYTE	modstop;
	UBYTE	speed;
	UBYTE	patt;
	WORD	destperd;
	UBYTE	volume;
	UBYTE	ciaspeed;
	UBYTE	ciaon;
	UBYTE	ntscon;
	UBYTE	resampling;
	UBYTE	sustain;
	};
struct  sampel {			// opis sampla
	UBYTE	volume;
	BYTE	*smpstrt;
	UWORD	smpstop;
	UWORD	repeat;
	UWORD	repeatlen;
	BYTE	finetune;
	};

WORD  periodtab[16][12*3]={
	{ 856,808,762,720,678,640,604,570,538,508,480,453,    // Tuning 0, Normal
	  428,404,381,360,339,320,302,285,269,254,240,226,
	  214,202,190,180,170,160,151,143,135,127,120,113},
	{ 850,802,757,715,674,637,601,567,535,505,477,450,    // Tuning 1
	  425,401,379,357,337,318,300,284,268,253,239,225,
	  213,201,189,179,169,159,150,142,134,126,119,113},
	{ 844,796,752,709,670,632,597,563,532,502,474,447,    // Tuning 2
	  422,398,376,355,335,316,298,282,266,251,237,224,
	  211,199,188,177,167,158,149,141,133,125,118,112},
	{ 838,791,746,704,665,628,592,559,528,498,470,444,    // Tuning 3
	  419,395,373,352,332,314,296,280,264,249,235,222,
	  209,198,187,176,166,157,148,140,132,125,118,111},
	{ 832,785,741,699,660,623,588,555,524,495,467,441,    // Tuning 4
	  416,392,370,350,330,312,294,278,262,247,233,220,
	  208,196,185,175,165,156,147,139,131,124,117,110},
	{ 826,779,736,694,655,619,584,551,520,491,463,437,    // Tuning 5
	  413,390,368,347,328,309,292,276,260,245,232,219,
	  206,195,184,174,164,155,146,138,130,123,116,109},
	{ 820,774,730,689,651,614,580,547,516,487,460,434,    // Tuning 6
	  410,387,365,345,325,307,290,274,258,244,230,217,
	  205,193,183,172,163,154,145,137,129,122,115,109},
	{ 814,768,725,684,646,610,575,543,513,484,457,431,    // Tuning 7
	  407,384,363,342,323,305,288,272,256,242,228,216,
	  204,192,181,171,161,152,144,136,128,121,114,108},
	{ 907,856,808,762,720,678,640,604,570,538,508,480,    // Tuning -8
	  453,428,404,381,360,339,320,302,285,269,254,240,
	  226,214,202,190,180,170,160,151,143,135,127,120},
	{ 900,850,802,757,715,675,636,601,567,535,505,477,    // Tuning -7
	  450,425,401,379,357,337,318,300,284,268,253,238,
	  225,212,200,189,179,169,159,150,142,134,126,119},
	{ 894,844,796,752,709,670,632,597,563,532,502,474,    // Tuning -6
	  447,422,398,376,355,335,316,298,282,266,251,237,
	  223,211,199,188,177,167,158,149,141,133,125,118},
	{ 887,838,791,746,704,665,628,592,559,528,498,470,    // Tuning -5
	  444,419,395,373,352,332,314,296,280,264,249,235,
	  222,209,198,187,176,166,157,148,140,132,125,118},
	{ 881,832,785,741,699,660,623,588,555,524,494,467,    // Tuning -4
	  441,416,392,370,350,330,312,294,278,262,247,233,
	  220,208,196,185,175,165,156,147,139,131,123,117},
	{ 875,826,779,736,694,655,619,584,551,520,491,463,    // Tuning -3
	  437,413,390,368,347,328,309,292,276,260,245,232,
	  219,206,195,184,174,164,155,146,138,130,123,116},
	{ 868,820,774,730,689,651,614,580,547,516,487,460,    // Tuning -2
	  434,410,387,365,345,325,307,290,274,258,244,230,
	  217,205,193,183,172,163,154,145,137,129,122,115},
	{ 862,814,768,725,684,646,610,575,543,513,484,457,    // Tuning -1
	  431,407,384,363,342,323,305,288,272,256,242,228,
	  216,203,192,181,171,161,152,144,136,128,121,114}};

APTR	modptr=0;	// miejsce modulu
APTR	smpptr=0;	// miejsce sampla

BYTE	debug=0;

// prototypy
ULONG	mixer(struct kupa);
ULONG	mixit(struct kupa);
void	savesample(ULONG,char *);
ULONG	loadmodule(char *);
UWORD	policzpatterny(BYTE *);
void	adresysampli(BYTE *,struct sampel *,UWORD);
WORD	findnote(char *,WORD);
WORD	calculate_pom(WORD,WORD,ULONG,ULONG,UBYTE);
WORD	findperiod(WORD,BYTE,BYTE);

ULONG	mixit(sinfo)
struct	kupa sinfo;
{
	if(modptr){
	  if(smpptr=AllocMem(MAXIM*2,MEMF_CLEAR|MEMF_PUBLIC)){
	    return(mixer(sinfo));
	  }
	  else{
	    printf(" Sorry, not enough memory to allocate sample buffor. \n");
	    return(0);
	  }
	}
	else{
	  printf(" You have to load module first.\n");
	  return(0);
	}
}

void	savesample(smplen,smpname)
ULONG	smplen;
char	*smpname;
{
	ULONG	smphandle=0;

	if(smplen){
	  if(smphandle=Open(smpname,MODE_NEWFILE)){
	    if( Write(smphandle,smpptr,smplen)!=-1){
	      Close(smphandle);
	      smphandle=0;
	    }
	    else{
	      printf(" Sorry, I can't save file. \n");
	    }
	  }
	  else{
	    printf(" Sorry, I can't open file to save. \n");
	  }
	}
	else{
	printf(" Nothing to save.\n");
	}
}

ULONG	loadmodule(modname)
char	*modname;
{
	ULONG	modhandle=0;
	ULONG	modlen=0;

	if(modhandle=Open(modname,MODE_OLDFILE)){
	  modlen=Seek(modhandle,0,OFFSET_END);
	  modlen=Seek(modhandle,0,OFFSET_BEGINNING);
	  if(modptr=AllocMem(modlen,MEMF_PUBLIC)){
	    Read(modhandle,modptr,modlen);
	    Close(modhandle);
	    modhandle=0;
	    if(debug){
	      printf(" Module length : %i\n",modlen);
	      printf(" Module name   : %s\n",modptr);
	      printf(" Module mark   : %4s\n",(ULONG)modptr+1080);
	    }
	    if( *((ULONG *)((ULONG)modptr+1080))!=*((ULONG *)"M.K.") ){
	      printf(" Sorry, this is not a module. \n ");
		  FreeMem(modptr,modlen);
	      modptr=0;
	      modlen=0;
	    }
	  }
	  else{
	    printf(" Sorry, not enough memory to load module. \n");
	    Close(modhandle);
		modhandle=0;
	  }
	}
	else{
	  printf(" Sorry, I can't find this module. \n");
	}
	return(modlen);
}	


main(argc, argv)
int 	argc;
char	*argv[];
{
	ULONG	modlen=0,smplen=0;
	struct	kupa sinfo={0,16,6,0,214,75,125,1,0,0,0};
	char 	*modname,*smpname;

	char opts[] = "gx";	// do opcji
	char option,*odata;
	int next;

	if(argc>=8){
	  modname=argv[1];
	  smpname=argv[2];
	  sinfo.patt=atoi(argv[3]);
	  sinfo.modstrt=atoi(argv[4]);
	  sinfo.modstop=atoi(argv[5]);
	  sinfo.volume=atoi(argv[6]);
	  sinfo.destperd=findnote(argv[7],0);

	// anti-lame
	if(sinfo.modstrt>63) sinfo.modstrt=63;
	if(sinfo.modstop>63) sinfo.modstop=63;
	if(sinfo.modstrt>=sinfo.modstop){
	  printf("  I won't play in backward mode.\n");
	  goto end;
	}


	  next = 8;
	  while((odata = argopt(argc,argv,opts,&next,&option)) != NULL){
	    switch(option){
	      case 'c':
	        sinfo.ciaon=1;
	        sinfo.ciaspeed=atoi(odata);
	        break;
	      case 'f':
	        sinfo.speed=atoi(odata);
	        break;
	      case 'n':
	        sinfo.ntscon=1;
	        break;
	      case 's':
	        sinfo.sustain=1;
	        break;
	      case 'd':
	        debug=1;
	        break;
	      case 'v':
	        sinfo.ciaon=0;
	        break;
	      case 'r':
	        sinfo.resampling=atoi(odata);
	        break;
	    }
	  }

	  modlen=loadmodule(modname);
	  if(modlen){
	    smplen=mixit(sinfo);
	    if(smplen){
	      savesample(smplen,smpname);
	    }
	  }
	}
	else
	  printf((char*)help);

end:
	if(smpptr)		FreeMem(smpptr,MAXIM*2);
	if(modptr)		FreeMem(modptr,modlen);
	exit(0);
}


WORD	findnote(note,fine)
char	*note;
WORD	fine;
{
	UWORD	index=0;
	UBYTE	nutka=0;

//	printf(note);
	nutka=*note;
	switch(nutka){
	  case 'C':
	    index=0;
	    break;
	  case 'D':
	    index=2;
	    break;
	  case 'E':
	    index=4;
	    break;
	  case 'F':
	    index=5;
	    break;
	  case 'G':
	    index=7;
	    break;
	  case 'A':
	    index=9;
	    break;
	  case 'B':
	    index=11;
	    break;
	};
	if( *(note+1)=='#') index++;
	index=index+((atoi(note+2)-1)*12);
	if(index>12*3) index=12*2;		//anti-lame
	return(periodtab[fine][index]);
}

/**********************************\
*                                  *
*               Mixer              *
*                                  *
\**********************************/

/*	analiza pozycji
	Info for each note:
	
	 _____byte 1_____   byte2_    _____byte 3_____   byte4_
	/                \ /      \  /                \ /      \
	0000          0000-00000000  0000          0000-00000000
	
	Upper four    12 bits for    Lower four    Effect command.
	bits of sam-  note period.   bits of sam-
	ple number.                  ple number.
*/

#define	FIND_ANYTHING(ptr)  (*((ULONG *)(ptr)))
#define	FIND_PERIOD(ptr)    (*((WORD *)ptr)&0x0fff)
#define	FIND_SMPNUMBER(ptr) (((*ptr)&(0xf0))+((*(ptr+2))>>4))
#define	FIND_EFFECT(ptr)    ((*(ptr+2))&0x0f)
#define	FIND_PARAMETR(ptr)  (*(ptr+3))


ULONG	mixer(sinfo)
struct	kupa sinfo;
{
	BYTE	*module;            // adres moduîu
	WORD	*fromword;          // pointery do zamiany z word'ow na
	BYTE	*tobyte;            // bajty
	ULONG	len;                // koncowa dlugosc sampla
	ULONG	h,i,j,k;            // zmienne do organizacji petli
	UWORD	hipatt=0;           // tu bedzie ilosc pattern'ów
	ULONG	ilenapoz;           // ile sampla wygenerowac
                                // do nastepnej pozycji
	WORD	*ptr2smp;           // pointery do generowania
	WORD	*ptr2smppom;        // zmiksowanego sampla ( w word'ach)
	UBYTE	*ptr2mod;           // pointer do przesuwania sie 
                                // po module
	UBYTE	speed;              // aktualna predkosc
	UBYTE	ciaspeed;
	UBYTE	ilepozycji;         // ile pozycji do zrobienia
	UWORD	pomoc;
	WORD	pom;
	WORD	probka0,probka1;
	UBYTE	sust;

	struct	sampel smp[32];     // tablica pointerow do sampli 
	struct	canal {             // co sie dzieje w kanale
		BYTE	nrsmp;       // numer odgrywanego sampla
		BYTE	volume;      // gîoônoôê sampla
		WORD	period;      // period
		ULONG	jump;
		ULONG	jumppos;
		UWORD	smppos;
		BYTE	*smpstrt;
		UWORD	smpstop;
		UWORD	smprepeat;
		UWORD	smprepeatlen;
		BYTE	volslide;    // do komendy - Axx
		UBYTE	last9;       // do komendy - 9xx
		UBYTE	actE9;       // do komendy - E9x
		UBYTE	notecut;     // do komendy - ECx
		WORD	trgetperd;   // do komendy - 3xx
		WORD	toneslide;   // ----------------
		WORD	lasttrget;   // ----------------
		WORD	lasttonesl;  // ----------------
		UBYTE	arpeggio;    // do komendy - 0xx
		WORD	saveperd;    // ----------------
		};
	struct	canal chan[4]={{0,0,0,0,0,0,0,0},
	                       {0,0,0,0,0,0,0,0},
	                       {0,0,0,0,0,0,0,0},
	                       {0,0,0,0,0,0,0,0}};
	struct	line {
		ULONG	anything;
		WORD	period;
		UBYTE	smpnumber;
		UBYTE	effect;
		UBYTE	parametr;
	};
	struct	line	trackline[4];


	sust=sinfo.sustain;
	module=modptr;
	ptr2smp=smpptr;
	hipatt=policzpatterny(module);
	adresysampli(module,smp,hipatt);
	speed=sinfo.speed;
	ciaspeed=sinfo.ciaspeed;
	if(sust){
	  ilepozycji=sinfo.modstop+1;
	  ptr2mod=module+1084+1024*sinfo.patt; // ustawienie sie na odpowiednia pozycje
	}
	else{
	  ilepozycji=sinfo.modstop-sinfo.modstrt+1;
	  ptr2mod=module+1084+1024*sinfo.patt+16*sinfo.modstrt; // ustawienie sie na odpowiednia pozycje
	}

	if(debug)  printf("   Destination Period = %i\n",sinfo.destperd);


	printf("   Wow! There will be %i positions. \n    >",ilepozycji);
	for(h=0;h<=(ilepozycji-1);h++){

	  if((sust)&&(h>=sinfo.modstrt)) sust=0;

	  for(i=0;i<=3;i++){
	    trackline[i].anything  = (ULONG)FIND_ANYTHING(ptr2mod);
	    trackline[i].period    = (WORD)FIND_PERIOD(ptr2mod);
	    trackline[i].smpnumber = (UBYTE)FIND_SMPNUMBER(ptr2mod);
	    trackline[i].effect    = (UBYTE)FIND_EFFECT(ptr2mod);
	    trackline[i].parametr  = (UBYTE)FIND_PARAMETR(ptr2mod);
	    ptr2mod=ptr2mod+4;
	  }

	  if(debug){
	    printf("\n"); 
	    for(i=0;i<=3;i++){
	      if(trackline[i].period) printf("  J-4");
	      else printf("  ---");
	      printf("%2x%1x%2x",trackline[i].smpnumber,trackline[i].effect,trackline[i].parametr);
	    }
	  }




	  for(i=0;i<=3;i++){
	    chan[i].volslide=0;
	    chan[i].actE9=0;
	    chan[i].toneslide=0;
	    chan[i].arpeggio=0;
	    chan[i].saveperd=0;
	    if(trackline[i].smpnumber){
 	      chan[i].nrsmp=trackline[i].smpnumber;
	      chan[i].volume=smp[chan[i].nrsmp].volume;
	    }
	    pomoc=0;
	    if(trackline[i].effect==0x03) pomoc=1;
	    if(trackline[i].effect==0x05) pomoc=1;
	    if( (trackline[i].period)&&(pomoc==0) ){
	      chan[i].period=trackline[i].period;
	      chan[i].trgetperd=0;
	      if( smp[chan[i].nrsmp].finetune)
	        chan[i].period = findperiod( chan[i].period, smp[chan[i].nrsmp].finetune,0);
	      chan[i].smpstrt=smp[chan[i].nrsmp].smpstrt;
	      chan[i].smpstop=smp[chan[i].nrsmp].smpstop;
	      chan[i].smprepeat=smp[chan[i].nrsmp].repeat;
	      chan[i].smprepeatlen=smp[chan[i].nrsmp].repeatlen;
	      chan[i].smppos=0;
	      chan[i].jumppos=0;
	    }
	    switch(trackline[i].effect){
	      case 0x0f:
	        if( (sinfo.ciaon)&&(trackline[i].parametr>0x1f) )
	          ciaspeed=trackline[i].parametr;
	        else
	          speed=trackline[i].parametr;
	        break;
	      case 0x0e:
	        switch(trackline[i].parametr>>4){
	          case 0x09:
	            chan[i].actE9=trackline[i].parametr&0x0f;
	          break;
	          case 0x0a:
	            chan[i].volume+=trackline[i].parametr&0x0f;
	          break;
	          case 0x0b:
	            chan[i].volume-=trackline[i].parametr&0x0f;
	          break;
	          case 0x0c:
	            chan[i].notecut=(trackline[i].parametr&0x0f)+1;
	          break;
	          case 0x02:
	            chan[i].period+=trackline[i].parametr&0x0f;
	            if( chan[i].period>findperiod(856,smp[chan[i].nrsmp].finetune,0) )
	              chan[i].period=findperiod(856,smp[chan[i].nrsmp].finetune,0);
	          break;
	          case 0x01:
	            chan[i].period-=trackline[i].parametr&0x0f;
	            if( chan[i].period<findperiod(113,smp[chan[i].nrsmp].finetune,0) )
	              chan[i].period=findperiod(113,smp[chan[i].nrsmp].finetune,0);
	          break;
	        }
	        break;
	      case 0x0c:
	        chan[i].volume=trackline[i].parametr;
	        break;
	      case 0x0a:
	        if( (trackline[i].parametr)&0xf0)
	          chan[i].volslide=(trackline[i].parametr>>4)&0x0f;
	        else
	          chan[i].volslide=-trackline[i].parametr;
	        break;
	      case 0x09:
	        if(trackline[i].parametr)
	          chan[i].last9=trackline[i].parametr;
	        pomoc=((UWORD)chan[i].last9)<<8;
	        if(pomoc>(chan[i].smpstop))
	          chan[i].smppos=chan[i].smprepeat;
	        else
	          chan[i].smppos=pomoc;
	        chan[i].jumppos=0;
	        break;
	      case 0x05:
	        if( (trackline[i].parametr)&0xf0)
	          chan[i].volslide=(trackline[i].parametr>>4)&0x0f;
	        else
	          chan[i].volslide=-trackline[i].parametr;
	        if(trackline[i].period){
	          chan[i].trgetperd=findperiod(trackline[i].period,smp[chan[i].nrsmp].finetune,0);
	          chan[i].lasttrget=chan[i].trgetperd;
	        }
	        else{
	          chan[i].trgetperd=chan[i].lasttrget;
	        }
	        if( chan[i].period>chan[i].trgetperd )
	          chan[i].toneslide=-chan[i].lasttonesl;
	        else
	          chan[i].toneslide=chan[i].lasttonesl;
	        if(chan[i].trgetperd==0) chan[i].toneslide=0;
	        break;
	      case 0x03:
	        if(trackline[i].period){
	          chan[i].trgetperd=findperiod(trackline[i].period,smp[chan[i].nrsmp].finetune,0);
	          chan[i].lasttrget=chan[i].trgetperd;
	        }
	        else{
	          chan[i].trgetperd=chan[i].lasttrget;
	        }
	        chan[i].lasttonesl=trackline[i].parametr;
	        if( chan[i].period>chan[i].trgetperd )
	          chan[i].toneslide=-trackline[i].parametr;
	        else
	          chan[i].toneslide=trackline[i].parametr;
	        if(chan[i].trgetperd==0) chan[i].toneslide=0;
	        break;
	      case 0x02:
	        chan[i].trgetperd=findperiod(856,smp[chan[i].nrsmp].finetune,0);
	        chan[i].toneslide=trackline[i].parametr;
	        break;
	      case 0x01:
	        chan[i].trgetperd=findperiod(113,smp[chan[i].nrsmp].finetune,0);
	        chan[i].toneslide=-trackline[i].parametr;
	        break;
	      case 0x00:
	        if(trackline[i].parametr){
	          chan[i].arpeggio=trackline[i].parametr;
	          chan[i].saveperd=chan[i].period;
	        }
	        break;
	    } 
	  }

	  // ile probek
	  if(sinfo.ciaon){
	    if(sinfo.ntscon)
	      ilenapoz=((CIAVALNTSC*5)/ciaspeed)/sinfo.destperd;
	    else
	      ilenapoz=((CIAVAL*5)/ciaspeed)/sinfo.destperd;
	  }
	  else{  
	    if(sinfo.ntscon)
	      ilenapoz=VBLVALNTSC/sinfo.destperd;
	    else
	      ilenapoz=VBLVAL/sinfo.destperd;
	  }

	  // mixowanie
	  for(i=0;i<=3;i++){
	  ptr2smppom=ptr2smp;
	  //printf("\n");
	    for(k=0;k<=(speed-1);k++){
	      // comman E9x retrig note
	      if(chan[i].actE9){
	        if( (k-(k/chan[i].actE9)*chan[i].actE9)==0 ){
	          chan[i].smppos=0;
	          chan[i].jumppos=0;
	          chan[i].smpstop=smp[chan[i].nrsmp].smpstop;
	        }
	      }
	      // comman ECx note cut
	      if(chan[i].notecut){
	        if( k==(chan[i].notecut-1) ){
	          chan[i].volume=0;
	        }
	      }
	      // command Axx volsliding
	      if((chan[i].volslide)&&(k!=0)){
	        chan[i].volume=chan[i].volume+chan[i].volslide;
	        if(chan[i].volume<0) chan[i].volume=0;
	        if(chan[i].volume>64) chan[i].volume=64;
	      }
	      // command 3xx tone sliding
	      if((chan[i].toneslide)&&(k!=0)){
	        //printf("!");
	        chan[i].period+=chan[i].toneslide;
	        if(chan[i].toneslide<0){
	          if(chan[i].period<chan[i].trgetperd)
	            chan[i].period=chan[i].trgetperd;
	        }
	        else{
	          if(chan[i].period>chan[i].trgetperd)
	            chan[i].period=chan[i].trgetperd;
	        }
	      }
	      // command 0xx arpeggio
	      if(chan[i].arpeggio){
                switch( k-(k/3)*3 ){
	          case 2:
	            chan[i].period=findperiod( chan[i].saveperd, smp[chan[i].nrsmp].finetune, chan[i].arpeggio&0x0f);
	            break;
	          case 1:
	            chan[i].period=findperiod( chan[i].saveperd, smp[chan[i].nrsmp].finetune, chan[i].arpeggio>>4);
	            break;
	          case 0:
	            chan[i].period=chan[i].saveperd;
	            break;
	        }
	      }

	      //printf(" %i",chan[i].period);

	      if(chan[i].period!=0)
	        chan[i].jump=(((ULONG)sinfo.destperd)<<16)/chan[i].period;
	      else
	        chan[i].jump=0;

	      // generowanie sampla
	      for(j=0;j<=ilenapoz;j++){
	        if((ULONG)ptr2smppom>=(ULONG)smpptr+MAXIM*2) break; // jesli przekroczymy bufor to stop

	        chan[i].smppos+=(UWORD)(chan[i].jumppos>>16);
	        chan[i].jumppos=chan[i].jumppos&0xffff;

	        if(chan[i].smppos>=chan[i].smpstop){
	           chan[i].smppos=chan[i].smprepeat+(chan[i].smppos-chan[i].smpstop);
	           chan[i].smpstop=chan[i].smprepeat+chan[i].smprepeatlen;
	        }

	        probka0=*(chan[i].smppos+chan[i].smpstrt);
	        probka1=*(chan[i].smppos+chan[i].smpstrt+1);
	        if((chan[i].smppos+1)>=chan[i].smpstop){
	            probka1=*(chan[i].smprepeat+chan[i].smpstrt);
	        }

	        pom=calculate_pom(probka0,probka1,chan[i].jumppos,chan[i].jump,sinfo.resampling);

	        if(sust==0){
	          *ptr2smppom+=(pom*chan[i].volume)/64;
	          ptr2smppom++;
	        }
	        chan[i].jumppos+=chan[i].jump;
	      }
	    }
	    if(chan[i].saveperd){
	      chan[i].period=chan[i].saveperd;
	    }
	  }
	  ptr2smp=ptr2smppom;
	  printf("*");
	}
	printf("\n");

	// obcinanie
	len=((ULONG)ptr2smp-(ULONG)smpptr)/2;
	fromword=smpptr;
	tobyte=smpptr;
	for(i=0;i<=len;i++){
	  pom=((*fromword++)*sinfo.volume)/100;
	  if(pom>127) pom=127;
	  if(pom<-128) pom=-128;
	  *tobyte++=pom;
	  if((i>>10)<<10==i)
	    printf("\r   hmm ... : %i ",i);
	}
	printf("\r   OK it's: %i \n",i);

	return(len);
}

WORD	findperiod(mainperiod,finetune,index)
WORD	mainperiod;
BYTE	finetune;
BYTE	index;
{
	UWORD	i;

	for(i=0;i<=12*3;i++)
	  if(mainperiod==periodtab[0][i]) break;
	i=i+index;
	if(i>=12*3) return(0);

	return(periodtab[finetune][i]);
}

WORD	calculate_pom(sample0,sample1,jumppos,jump,method)
WORD	sample0;
WORD	sample1;
ULONG	jumppos;
ULONG	jump;
UBYTE	method;
{
	WORD	a;
	WORD	i;
	ULONG	myjumppos;

	if(jump==0) return(0);

	myjumppos=jumppos;

    if(method){
	  for(i=1;(jump)<(0x10000/(i+1));i++);
	  //printf("i= %i\n",i);
	  if(i>1){
	    if(jumppos<((0x10000/i)*(i-1)))
	      return(sample0);
	    else{
	      myjumppos=(jumppos-((0x10000/i)*(i-1)))*i;
	    }
	  }
	}

	a=sample1-sample0;
	a=(WORD)(((LONG)myjumppos*a)>>16);
	a=a+sample0;
	return(a);
}


UWORD	policzpatterny(module)
BYTE	*module;
{
	UWORD	pomoc;
	UWORD	i;
	UWORD	hipat=0;

	for(i=0;i<=127;i++){
	  pomoc=*((UBYTE *)(module+952+i));
	  hipat=(hipat>pomoc)?hipat:pomoc;
	}
	hipat++;
	return(hipat);
}



void	adresysampli(module,smp,hipatt)
BYTE	*module;
struct	sampel smp[];		// tablica pointerow do sampli 
UWORD	hipatt;
{
	UWORD	i;
	UWORD	pomoc;

	smp[1].smpstrt=module+1084+1024*hipatt;
	smp[1].smpstop=(*((UWORD *)(module+42)))*2;
	smp[1].volume=*((UBYTE *)(module+45));
	smp[1].repeat=(*((UWORD *)(module+46)))*2;
	smp[1].repeatlen=(*((UWORD *)(module+48)))*2;
	smp[1].finetune=*((UBYTE *)(module+44));
	for(i=2;i<=31;i++){
	  pomoc=*((UWORD *)(module+42+30*(i-2)));
	  smp[i].smpstrt=smp[i-1].smpstrt+pomoc*2;
	  smp[i].smpstop=(*((UWORD *)(module+42+30*(i-1))))*2;
	  smp[i].volume=*((UBYTE *)(module+45+30*(i-1)));
	  smp[i].repeat=(*((UWORD *)(module+46+30*(i-1))))*2;
	  smp[i].repeatlen=(*((UWORD *)(module+48+30*(i-1))))*2;
	  smp[i].finetune=*((UBYTE *)(module+44+30*(i-1)));
      if(smp[i].repeat)  smp[i].smpstop=smp[i].repeat+smp[i].repeatlen;
	}

	if(debug){
	  for(i=1;i<=8;i++)
	    printf("%2i vol %-2x strt $%-6x stop $%-4x %-5irepeat $%-4xrepeatlen $%-4xfinetune %1i\n",i,smp[i].volume,smp[i].smpstrt,smp[i].smpstop,smp[i].smpstop,smp[i].repeat,smp[i].repeatlen,smp[i].finetune);
	}
}

