#include <exec/memory.h>
#include "inc.h"
#include "defs.h"
#include "req_manx_5.c"
#include "zz_pointer.h"
#include <exec/semaphores.h>

#include <devicetoolkits/input.h>
#include <deviceToolKits/proto/Input.h>
#include <deviceToolKits/InputBase.h>

extern DTInput_t            Unit0;
extern struct   Interrupt   handler_setup;
extern struct Library *SysBase;

struct SignalSemaphore *Semaphore;


/* funcs.c */

void Error(char *string);
int OpenSingleRequester(int xp, int yp);
int OpenMultiRequester(int xp, int yp);
void OpenStuff(void);
void CloseStuff(void);
int WaitForK1(void);
long FileLen(FILE *fp);
void LoadBank(int banknr);
void SaveBank(int banknr);
void SaveSound(int soundnr);
void LoadSound(int soundnr);
void SaveAllSounds(int banknr);
void TransmitCurrentBank(int banknr);
void TransmitBank(int banknr);
void TransmitSingleSound(int soundnr);
void GetBank(int banknr);
void LoadMulti(void);
void SaveMulti(void);
void SendDump(void);
void GetDump(void);
void TransmitSingleMulti(int soundnr);
void LoadDump(char *dumpname);
void SaveDump(void);
void Display(void);
void GetMulti(void);
void SendMulti(void);
void ProgChange(int);
void AllNotesOff(void);			
void NoteOff(int note,int channel);
void NoteOn(int note,int vel,int channel);
BOOL Exists(char *);
char *filerequester(char *dir,char *filename,char *title);

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void Error(char *string)
{
	if (ReqBase == NULL) BoolRequest(string,"Quit","Quit");
				    else MyReq(string,NULL," Ok ");
	CloseStuff();
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

int OpenSingleRequester(int xp,int yp)
{
	int i,select;

	if (yp+win->TopEdge-10+52 > HOEHE-10) 
	{
		MoveWindow(win,-(win->LeftEdge),-(win->TopEdge));
		return(-1);
	}
	
	if (!(xp<15 || xp>615 || yp<28 || yp>189))
	{
		if (xp>480) xp=480;
		if (yp>180) yp=180;
		Make_SingleReqWindow(xp-10,yp+8);
		SetAPen(rp2,1);
		for (i=11;i<70;i+=10)	Line(win2,1,i,win2->Width-1,i);
		MyCenter(win2,9, "Edit sound");
		MyCenter(win2,19,"Load sound");
		MyCenter(win2,29,"Save sound");
		MyCenter(win2,39,"Transmit sound");
		MyCenter(win2,49,"Copy to");
		MyCenter(win2,59,"Swap with");
		MyCenter(win2,69,"Cancel");

Loop:	;
		WaitPort(win2->UserPort);
		while(mesg=(struct IntuiMessage *) GetMsg(win2->UserPort))
		{
			if (mesg->Class == MOUSEBUTTONS && mesg->Code == SELECTDOWN)
			{	
				select=(mesg->MouseY)/10;
				ReplyMsg((struct Message *) mesg);
				Delay(5);
				WaitPort(win2->UserPort);
				CloseWindow(win2);
				goto Ende;
			}
			else 
			{	
				ReplyMsg((struct Message *) mesg);
				goto Loop;
			}
		}
	}	
	Ende: return(select);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

int OpenMultiRequester(int xp,int yp)
{
	int i,select;

	if (yp+win->TopEdge-10+52 > HOEHE-10) 
	{
		MoveWindow(win,-(win->LeftEdge),-(win->TopEdge));
		return(-1);
	}
	
	if (!(xp<15 || xp>315 || yp<28 || yp>189))
	{
		if (xp>480) xp=480;
		if (yp>180) yp=180;
		Make_MultiReqWindow(xp-10,yp+8);
		SetAPen(rp6,1);
		for (i=11;i<50;i+=10)	Line(win6,1,i,win6->Width-1,i);
		MyCenter(win6,9,"Edit multi");
		MyCenter(win6,19,"Transmit multi");
		MyCenter(win6,29,"Copy to");
		MyCenter(win6,39,"Swap with");
		MyCenter(win6,49,"Cancel");

Loop:	;
		WaitPort(win6->UserPort);
		while(mesg=(struct IntuiMessage *) GetMsg(win6->UserPort))
		{
			if (mesg->Class == MOUSEBUTTONS && mesg->Code == SELECTDOWN)
			{	
				select=(mesg->MouseY)/10;
				ReplyMsg((struct Message *) mesg);
				Delay(5);
				WaitPort(win6->UserPort);
				CloseWindow(win6);
				goto Ende;
			}
			else 
			{	
				ReplyMsg((struct Message *) mesg);
				goto Loop;
			}
		}
	}	
	Ende: return(select);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void OpenStuff(void)
{
	IntuitionBase=(struct IntuitionBase *) OpenLibrary("intuition.library",0);
	if (IntuitionBase==NULL) 	Error("Can't open intuition.library");
	if (IntuitionBase->LibNode.lib_Version >=37) KICKZWO=TRUE;

	ReqBase=(struct ReqBase *) 	OpenLibrary("req.library",REQVERSION);
	if (ReqBase==NULL) 			Error("Can't open req.library, I need version 2.5 or higher");

	GfxBase=(struct GfxBase *) 	OpenLibrary("graphics.library",0);
	if (GfxBase==NULL) 			Error("Can't open graphics.library");

	DosBase=(struct DosBase *) 	OpenLibrary("dos.library",0);
	if (DosBase==NULL) 			Error("Can't open dos.library");

	MidiBase=(struct MidiBase *) OpenLibrary(MIDINAME,MIDIVERSION);
	if (MidiBase==NULL) 		Error("Can't open midi.library");

	DiskfontBase=(struct DiskfontBase *) OpenLibrary("diskfont.library",0);
	if (DiskfontBase==NULL) 	Error("Can't open diskfont.library");

	IconBase=(struct IconBase *) OpenLibrary("icon.library",0);
	if (IconBase==NULL)			Error("Can't open icon.library");	

	source=CreateMSource(NULL,NULL);
	if (source==NULL) 			Error("Can't create midi source");

	dest=CreateMDest(NULL,NULL);
	if (dest==NULL) 			Error("Can't create midi destination");

	inroute=MRouteDest("MidiIn",dest,&routeinfo);
	if (inroute==NULL) 			Error("Can't create midi route destination");

	outroute=MRouteSource(source,"MidiOut",NULL);
	if (outroute == NULL) 		Error("Can't create midi route source");

	if (!zz_pointer_open())		Error("Can't get sleepy pointer");

	if (SysBase->lib_Version>=37) KICKZWO=TRUE;


	Semaphore=(struct SignalSemaphore *) AllocVec(sizeof(struct SignalSemaphore),MEMF_PUBLIC | MEMF_CLEAR);

	Semaphore->ss_Link.ln_Pri=0;
	Semaphore->ss_Link.ln_Name="K1-II Editor";
	AddSemaphore(Semaphore);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/
	
void CloseStuff(void)
{
	SetTaskPri(FindTask(NULL),0);
	setenv("K1-LIB","FALSE");

	Forbid();
		RemSemaphore(Semaphore);
		ObtainSemaphore(Semaphore);
		ReleaseSemaphore(Semaphore);
		FreeVec(Semaphore);
	Permit();


	myprocess->pr_WindowPtr = olderrorwindow;
		
	DTInputRemHandler(Unit0,&handler_setup);
	DTInputFree(Unit0);

	if (inroute != NULL)		DeleteMRoute(inroute);
	if (outroute != NULL)		DeleteMRoute(outroute);
	if (source != NULL)			DeleteMSource(source);
	if (dest != NULL)			DeleteMDest(dest);
	if (textfont != NULL)		CloseFont(textfont);

	if (win != NULL) 			CloseWindow(win);
	if (SCREEN != NULL) 		CloseScreen(scr);
	if (IntuitionBase != NULL)	CloseLibrary(IntuitionBase);
	
	if (GfxBase != NULL)		CloseLibrary(GfxBase);
	if (MidiBase != NULL)		CloseLibrary(MidiBase);
	if (DosBase != NULL)		CloseLibrary(DosBase);
	if (DiskfontBase != NULL)	CloseLibrary(DiskfontBase);
	if (IconBase != NULL)		CloseLibrary(IconBase);
	if (ReqBase != NULL)	
	{
								PurgeFiles(&ReqStruct);
								CloseLibrary(ReqBase);
	}

	if (SCREEN == NULL)			SetOldColours();
	exit(0);
}
 
/**********************************************************************************/
/***	 Test ob K1 überhaupt vorhanden ist (während des Programmablaufs)       ***/
/**********************************************************************************/

int  WaitForK1(void)
{
	unsigned char buf[5];
	int i,j;

	SetTitle("Waiting....");
	for (j=0;j<=1;j++)
	{
		for (i=0;i<=15;i++)
		{
			buf[0]=0xf0;	buf[1]=0x40;	buf[2]=i;
			buf[3]=0x60;	buf[4]=0xf7;
			PutMidiMsg(source,buf);
			Delay(2);
	
			while(packet=GetMidiPacket(dest))
			{
				if (packet->MidiMsg[OFFS_FUNC]==K1_MIA)
				{
					MASTERCHANNEL=i;
					return(i);
				}
				FreeMidiPacket(packet);
			}
		}
	}
	return(-1);
}			

/**********************************************************************************/
/***  			 Ermittelt die Länge eines bereits geöffneten Files             ***/
/**********************************************************************************/

long FileLen(FILE *fp)
{
	long len;
	
	fseek(fp,0,SEEK_END);
	len=ftell(fp);
	fseek(fp,0,SEEK_SET);
	return(len);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void LoadBank(int banknr)
{
	FILE *fp,*fopen();
	int i,n;
	long len;
	unsigned char dummy;

	SetTitle("Load bank");

	strcpy(&answer[0],filerequester(bankdir,NULL,"Load bank"));	

	if (strlen(answer) != 0)
	{
		i=0;
		fp=fopen(answer,"r");
		if (fp==NULL)
		{
			MyReq("Can't open file",NULL," Ok ");
			goto Ende;
		}
		len=FileLen(fp);

		if (len==2825)
		{
			for (i=0;i<=7;i++) dummy=fgetc(fp);		

			for (n=0;n<=31;n++)
				for (i=0;i<=87;i++)
					s[banknr][n][i]=fgetc(fp);

			fclose(fp);
			strncpy(bankname[banknr],filename,20);
			goto Ende;
		}

		if (len==2816)
		{
			for (n=0;n<=31;n++)
				for (i=0;i<=87;i++)
					s[banknr][n][i]=fgetc(fp);

			fclose(fp);
			strncpy(bankname[banknr],filename,20);
			goto Ende;
		}
		
		if (len==2432 || len==2441)
				MyReq("Not K1 sound bank, seems to be a multi-patch",NULL," Ok ");
		else
				MyReq("This is not a K1 single sound bank !",NULL," Ok ");
	}
Ende: strcpy(bankdir,ReqStruct.Dir);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void SaveBank(int banknr)
{
	FILE *fp,*fopen();
	int i,n;

	SetTitle("Save bank");

	strcpy(&answer[0],filerequester(bankdir,bankname[banknr],"Save bank"));	

	if (strlen(answer) != 0)
	{
		if (Exists(answer))
			if (!MyReq("File exists, overwrite it ?"," Yes "," No ")) goto Ende;

		i=0;
		fp=fopen(answer,"w");
		if (fp==NULL)
		{
			MyReq("Can't create file",NULL," Ok ");
			goto Ende;
		}
		fputc(MS_SYSEX,fp);	fputc(0x40,fp);	fputc(0x00,fp);	fputc(0x21,fp);
		fputc(0x00,fp);		fputc(0x03,fp);	fputc(0x00,fp);	fputc(0x00,fp);

		for (n=0;n<=31;n++)
			for (i=0;i<=87;i++)
				fputc((int)s[banknr][n][i],fp);

		fputc(MS_EOX,fp);
		fclose(fp);
	}
	Ende: strcpy(bankdir,ReqStruct.Dir);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void SaveSound(int soundnr)
{
	FILE *fp,*fopen();
	char name[11];
	int i;

	SetTitle("Save sound");

	for (i=0;i<=9;i++) name[i]=s[soundnr/32][soundnr%32][i];
	name[10]='\0';
		
	strcpy(&answer[0],filerequester(sounddir,name,"Save sound"));	

	if (strlen(answer) != 0)
	{
		if (Exists(answer))
			if (!MyReq("File exists, overwrite it ?"," Yes "," No ")) goto Ende;
		
		fp=fopen(answer,"w");
		if (fp==NULL)
		{
			MyReq("Can't create file",NULL," Ok ");
			goto Ende;
		}

		for (i=0;i<=87;i++)	fputc((int)s[soundnr/32][soundnr%32][i],fp);
		fclose(fp);
	}
	Ende: strcpy(sounddir,ReqStruct.Dir);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void LoadSound(int soundnr)
{
	FILE *fp,*fopen();
	int i,notdisplay;

	SetTitle("Load sound");

	if (soundnr>=1000)
	{
		notdisplay=1;
		soundnr-=1000;
	}
	else notdisplay=0;

	strcpy(&answer[0],filerequester(sounddir,NULL,"Load sound"));	

	if (strlen(answer) != 0)
	{
		ZZ_POINTER(win);	
		fp=fopen(answer,"r");
		if (fp==NULL)
		{
			MyReq("Can't open file",NULL," Ok ");
			goto Ende;
		}
		if (FileLen(fp) != 88)
		{
			MyReq("This is not a K1 sound file",NULL," Ok ");
		}
		else
		{
			for (i=0;i<=87;i++)	s[soundnr/32][soundnr%32][i]=fgetc(fp);
		}
		fclose(fp);
	}
	Ende: if (notdisplay != 1) Display();
	strcpy(sounddir,ReqStruct.Dir);
	CLEAR_POINTER(win);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void SaveAllSounds(int banknr)
{
	FILE *fp,*fopen();
	char filename[255],name[11];
	int i,soundnr;

	SetTitle("Save all sounds");
	ZZ_POINTER(win);
	for (soundnr=0;soundnr<=31;soundnr++)
	{
		for (i=0;i<=9;i++) name[i]=s[banknr][soundnr][i];
		name[10]='\0';
		strcpy(filename,"kawai:sounds/");
		strcat(filename,name);

		fp=fopen(filename,"w");
		if (fp==NULL) goto Ende;
		
		for (i=0;i<=87;i++)	fputc((int)s[banknr][soundnr][i],fp);

		fclose(fp);
		Ende: ;
	}
	CLEAR_POINTER(win);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void TransmitCurrentBank(int banknr)
{
	int n,i;
	unsigned char buf[97];

	ZZ_POINTER(win);
	SetTitle("Transmit current bank");

	for (n=0;n<=31;n++)
	{
		buf[0]=MS_SYSEX; buf[1]=0x40; buf[2]=MASTERCHANNEL; buf[3]=0x20;
		buf[4]=0x00; buf[5]=0x03; buf[6]=0x00; buf[7]=n+32*banknr;

		for (i=0;i<=87;i++)	buf[8+i]=s[banknr][n][i];
		buf[96]=MS_EOX;
		PutMidiMsg(source,buf);
	}

    ProgChange(32*banknr);
	CLEAR_POINTER(win);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void TransmitBank(int banknr)
{
	FILE *fp,*fopen();
	unsigned char buf[97];
	int i,n;
	long len;	

	ZZ_POINTER(win);
	SetTitle("Load bank and send it to K1");

	if (MyReq("        Are you shure ?\nCurrent bank will be erased !","With pleasure !","Am I crazy ?") == FALSE) goto Ende2;

	strcpy(&answer[0],filerequester(bankdir,NULL,"Transmit bank"));	

	if (strlen(answer) != 0)
	{
		fp=fopen(answer,"r");
		if (fp==NULL)
		{
			MyReq("Can't open file",NULL," Ok ");
			goto Ende;
		}
		len=FileLen(fp);		

		if (len==2825)
		{
			for (i=0;i<=7;i++) n=fgetc(fp);	/* Header überlesen */
			for (n=0;n<=31;n++)
			{
				buf[0]=MS_SYSEX; buf[1]=0x40; buf[2]=MASTERCHANNEL; buf[3]=0x20;
				buf[4]=0x00; buf[5]=0x03; buf[6]=0x00; buf[7]=n+32*banknr;
	
				for (i=0;i<=87;i++)	buf[8+i]=fgetc(fp);
				buf[96]=MS_EOX;
				PutMidiMsg(source,buf);
			}
			fclose(fp);
			goto Ende;
		}
		
		if (len==2816)
		{
			for (n=0;n<=31;n++)
			{
				buf[0]=MS_SYSEX; buf[1]=0x40; buf[2]=MASTERCHANNEL; buf[3]=0x20;
				buf[4]=0x00; buf[5]=0x03; buf[6]=0x00; buf[7]=n+32*banknr;
	
				for (i=0;i<=87;i++)	buf[8+i]=fgetc(fp);
				buf[96]=MS_EOX;
				PutMidiMsg(source,buf);
			}
			fclose(fp);
			goto Ende;
		}

		MyReq("This is not a K1 single sound bank !",NULL," Ok ");	
	}
	Ende: ;
	
    ProgChange(32*banknr);
	strcpy(bankdir,ReqStruct.Dir);
	Ende2: 	CLEAR_POINTER(win);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void TransmitSingleSound(int soundnr)
{
	int i;
	unsigned char buf[97];

	buf[0]=MS_SYSEX; buf[1]=0x40; buf[2]=MASTERCHANNEL; buf[3]=0x20;
	buf[4]=0x00; buf[5]=0x03; buf[6]=0x00; buf[7]=soundnr;

	for (i=0;i<=87;i++)	buf[8+i]=s[soundnr/32][soundnr%32][i];
	buf[96]=MS_EOX;
	PutMidiMsg(source,buf);
	Delay(1);

    ProgChange(soundnr);
}

/**********************************************************************************/
/***   					  	Bank vom K1 anfordern                   		 	***/
/**********************************************************************************/

void GetBank(int banknr)
{
	UBYTE *msg,buf[9],d[2600];
	int i,n,fo,chn;
	FILE *fp,*fopen();

	MASTERCHANNEL=chn=WaitForK1();
	if (chn == -1)
	{
		i=MyReq("Error: K1 not present",NULL," Ok ");
		goto Ende;
	}

	SetTitle("Get bank from K1");

Loop: ZZ_POINTER(win);
	fo=creat("ram:k1-bank",0666);
	if (fo != -1)
	{
		buf[0]=0xf0;	buf[1]=0x40;
		buf[2]=chn; 	buf[3]=0x01;
		buf[4]=0x00;	buf[5]=0x03;
		buf[6]=0x00;	buf[7]=32*(banknr%2);
		buf[8]=0xf7;
		PutMidiMsg(source,buf);
		Delay(3);			

		WaitPort(dest->DestPort);
		if (packet = GetMidiPacket(dest)) 
		{
			if (write(fo,packet->MidiMsg,packet->Length) != packet->Length); 
		}
		close(fo);
		
		if (packet->Length == 2825)
		{
			fp=fopen("ram:k1-bank","r");
			for (i=0;i<=7;i++) n=fgetc(fp);		/* Midi-Header überlesen */
			for (n=0;n<=31;n++)
			{
				for (i=0;i<=87;i++)	s[banknr][n][i]=fgetc(fp);
			}
			strcpy(bankname[banknr],"");
			fclose(fp);
		}
		else goto Loop;
		DeleteFile("ram:k1-bank");
		FreeMidiPacket(packet);
	}
	else
	{
		MyReq("Can't create temporary file in RAM-Disk",NULL," Ok ");	
	}
	Ende: CLEAR_POINTER(win);
}

/**********************************************************************************/
/***   						 Laden eines Multi-Patches                          ***/
/**********************************************************************************/

void LoadMulti(void)
{
	FILE *fp,*fopen();
	int i,n;
	long len;

	SetTitle("Load multi-patch");

	strcpy(&answer[0],filerequester(multidir,NULL,"Load multi"));	

	if (strlen(answer) != 0)
	{
		i=0;
		fp=fopen(answer,"r");
		if (fp==NULL)
		{
			MyReq("Can't open file",NULL," Ok ");
			goto Ende;
		}
		len=FileLen(fp);

		if (len==2432)
		{
			for (n=0;n<=31;n++)
			{
				for (i=0; i<=75; i++)
				{
					m[n][i]=fgetc(fp);
				}
			}
			strcpy(multiname,filename);
			fclose(fp);
			goto Ende;
		}
	
		if (len==2441)
		{
			for (i=0;i<=7;i++) n=fgetc(fp); 

			for (n=0;n<=31;n++)
				for (i=0; i<=75; i++)
					m[n][i]=fgetc(fp);

			strcpy(multiname,filename);
			fclose(fp);
			goto Ende;
		}
		
		MyReq("Sorry, this is not a K1 multi-patch",NULL," Ok ");
		fclose(fp);	
	}
Ende: 	Display();
	strcpy(multidir,ReqStruct.Dir);
}

/**********************************************************************************/
/***					Saven eines Multi-Patches                               ***/
/**********************************************************************************/

void SaveMulti(void)
{
	FILE *fp,*fopen();
	int i,n;

	SetTitle("Save multi-patch");

	strcpy(&answer[0],filerequester(multidir,multiname,"Save multi"));	

	if (strlen(answer) != 0)
	{
		if (Exists(answer))
			if (!MyReq("File exists, overwrite it ?"," Yes "," No ")) goto Ende;

		i=0;
		fp=fopen(answer,"w");
		if (fp==NULL)
		{
			MyReq("Can't create file",NULL," Ok ");
			goto Ende;
		}

		for (n=0;n<=31;n++)
			for (i=0;i<=75;i++)
				fputc((int)m[n][i],fp);

		fclose(fp);
	}
	Ende: strcpy(multidir,ReqStruct.Dir);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void SendDump(void)
{
	unsigned char buf[90];

	SetTitle("Send dump to K1");

	TransmitCurrentBank(0);
	TransmitCurrentBank(1);
	SendMulti();
}

/**********************************************************************************/
/*** 					Multipatch von K1 holen                                 ***/
/**********************************************************************************/

void GetDump(void)
{
	SetTitle("Get dump from K1");
	
	GetBank(0); Delay(2);
	GetBank(1); Delay(2);
	GetMulti(); Delay(2);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void TransmitSingleMulti(int soundnr)
{
	int i;
	unsigned char buf[97];

	buf[0]=MS_SYSEX; buf[1]=0x40; buf[2]=MASTERCHANNEL; buf[3]=0x20;
	buf[4]=0x00; buf[5]=0x03; buf[6]=0x00; buf[7]=64+soundnr;

	for (i=0;i<=75;i++)	buf[8+i]=m[soundnr][i];
	buf[84]=MS_EOX;
	PutMidiMsg(source,buf);
	Delay(2);

	ProgChange(64+soundnr);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void LoadDump(char *dumpname)
{
	FILE *fp,*fopen();
	int i,n;
	long len;
	unsigned char dummy;
	char string[255];

	SetTitle("Load dump");

	if (dumpname != NULL)
	{
		strcpy(string,dumpdir);
		strcat(string,dumpname);
		strcpy(answer,string);
		goto Load;
	}

	strcpy(answer,filerequester(dumpdir,NULL,"Load dump"));	

	if (strlen(answer) != 0)
	{
Load:	fp=fopen(answer,"r");
		len=FileLen(fp);

		if (len==8082)
		{
			for (n=0;n<=31;n++)						/* 1. Bank lesen */			
				for (i=0;i<=87;i++)
					s[0][n][i]=fgetc(fp);

			for (n=0;n<=31;n++) 					/* 1. Bank lesen */			
				for (i=0;i<=87;i++)
					s[1][n][i]=fgetc(fp);
			
			for (i=0;i<=17;i++) n=fgetc(fp);		/* Lücke überlesen */

			for (n=0;n<=31;n++)
				for (i=0;i<=75;i++)
					m[n][i]=fgetc(fp);

			fclose(fp);
			goto Ende;
		}
		else MyReq("This is not a K1 dump file",NULL," Ok ");	
	}

Ende: Display();
	strcpy(bankname[0],"");
	strcpy(bankname[1],"");
	strcpy(multiname,"");
	if (ReqStruct.Dir) strcpy(dumpdir,ReqStruct.Dir);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************	************************/

void SaveDump(void)
{
	FILE *fp,*fopen();
	int i,n;

	SetTitle("Save dump");

	strcpy(&answer[0],filerequester(dumpdir,NULL,"Save dump"));	

	if (strlen(answer) != 0)
	{
		if (Exists(answer))
			if (!MyReq("File exists, overwrite it ?"," Yes "," No ")) goto Ende;

		i=0;
		fp=fopen(answer,"w");
		if (fp==NULL)
		{
			("Can't create file");
			goto Ende;
		}

		for (n=0;n<=31;n++)						/* 1. Bank */
			for (i=0;i<=87;i++)
				fputc((int)s[0][n][i],fp);

		for (n=0;n<=31;n++)						/* 2. Bank */
			for (i=0;i<=87;i++)
				fputc((int)s[1][n][i],fp);

		for (i=0;i<=17;i++) fputc((int)0,fp);	/* Lücke auffüllen */

		for (n=0;n<=31;n++)						/* Multi-Bank */
			for (i=0;i<=75;i++)
				fputc((int)m[n][i],fp);

		fclose(fp);
	}
	Ende: 
	if (ReqStruct.Dir) strcpy(dumpdir,ReqStruct.Dir);
}


/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void Display(void)
{
	if (multi==0) DisplayBank();
			else  DisplayMulti();
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void GetMulti(void)
{
	UBYTE *msg,buf[9],d[2600];
	int i,n,fo,chn;
	FILE *fp,*fopen();

	ZZ_POINTER(win);
	MASTERCHANNEL=chn=WaitForK1();	
	if (chn == -1)
	{
		i=MyReq("Error: K1 not present",NULL," Ok ");
		goto Ende;
	}

	SetTitle("Get multi-patch from K1");

Loop: ;
	fo=creat("ram:k1-bank",0666);
	if (fo != -1)
	{
		buf[0]=0xf0;	buf[1]=0x40;
		buf[2]=chn;		buf[3]=0x01;
		buf[4]=0x00;	buf[5]=0x03;
		buf[6]=0x00;	buf[7]=64;
		buf[8]=0xf7;
		PutMidiMsg(source,buf);
		Delay(5);

		WaitPort(dest->DestPort);
		if (packet = GetMidiPacket(dest)) 
		{
			if (write(fo,packet->MidiMsg,packet->Length) != packet->Length); 
		}
		close(fo);
		
		if (packet->Length == 2441)
		{
			fp=fopen("ram:k1-bank","r");
			for (i=0;i<=7;i++) n=fgetc(fp);		/* Midi-Header überlesen */

			for (n=0;n<=31;n++)
				for (i=0;i<=75;i++)
					m[n][i]=fgetc(fp);

			strcpy(multiname,"");
			fclose(fp);
		}
		else goto Loop;
		DeleteFile("ram:k1-bank");
		FreeMidiPacket(packet);
	}
	else
	{
		MyReq("Can't create temporary file in RAM-Disk",NULL," Ok ");	
	}
	Ende: CLEAR_POINTER(win);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void SendMulti(void)
{
	int i,n;
	unsigned char buf[97];

	SetTitle("Send multi-patch to K1");

	ZZ_POINTER(win);
	for (n=0;n<=31;n++) 
	{
		buf[0]=MS_SYSEX; buf[1]=0x40; buf[2]=MASTERCHANNEL; buf[3]=0x20;
		buf[4]=0x00; buf[5]=0x03; buf[6]=0x00; buf[7]=64+n;

		for (i=0;i<=75;i++)	buf[8+i]=m[n][i];
		buf[84]=MS_EOX;
		PutMidiMsg(source,buf);
		Delay(1);
	}
	Delay(5);

    ProgChange(64);

	CLEAR_POINTER(win);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void ProgChange(int nr)
{
    unsigned char buf[2];

	if (nr>=64 && nr<96)
	{
		buf[0]=192+MASTERCHANNEL;
    	buf[1]=nr-1;
    	PutMidiMsg(source,buf);
		Delay(2);	
	}

	if (nr<64)
	{
		buf[0]=192+MASTERCHANNEL;
    	buf[1]=nr+1;
    	PutMidiMsg(source,buf);
		Delay(2);	
	}

    buf[0]=192+MASTERCHANNEL;
    buf[1]=nr;
    PutMidiMsg(source,buf);
	Delay(2);	
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void NoteOn(int note,int vel,int channel)
{
	UBYTE buf[3];

	buf[0] = MS_NOTEON | channel;
	buf[1] = note;
	buf[2] = vel;
	PutMidiMsg(source,buf);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void NoteOff(int note,int channel)		
{	
	UBYTE buf[3];

	buf[0] = MS_NOTEOFF | channel;
	buf[1] = note;
	buf[2] = 64;
	PutMidiMsg(source,buf);
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void AllNotesOff(void)			
{
	UBYTE buf[3];

	buf[0] = MS_MODE | MASTERCHANNEL;
	buf[1] = MM_ALLOFF;		
	buf[2] = 0;
	PutMidiMsg(source,buf);	
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

BOOL Exists(char *file)
{
	struct Lock *lock;

	lock=Lock(file,ACCESS_READ);
	if (lock==NULL) 	return(FALSE);
	UnLock(lock);
	return(TRUE);	
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

void Unkown(void)
{
	char str[]={0x44,0x65,0x64,0x69,0x63,0x61,0x74,0x65,0x64,0x20,0x74,0x6f,0x20,0x44,0x6f,0x72,0x6f,0x74,0x68,0x65,0x65,00};
}

/**********************************************************************************/
/***                                                                            ***/
/**********************************************************************************/

char *filerequester(char *dir,char *filename,char *title)
{
	char answer[255];	
	
	if (dir==NULL) 		dir	    =(char *)"";
	if (filename==NULL) filename=(char *)"";

	answer[0] = 0;

	ReqStruct.PathName 		= answer;
	ReqStruct.Dir 			= dir;
	ReqStruct.File 			= filename;
	ReqStruct.Title 		= title;
	ReqStruct.VersionNumber =REQVERSION;
	ReqStruct.Flags 		= FRQCACHINGM+(SCREEN != NULL ? FRQNODRAGM : NULL);

	if (FileRequester(&ReqStruct)) return(&answer[0]);
							else   return((char *)"");
}