#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<dos.h>
#include	"goldplay.h"

typedef	unsigned long int	longword;
typedef	unsigned int		word;

void 	far	pascal	(*saskinit) 	();
void	far	pascal	(*sinitialize) 	();
void	far	pascal	(*sloadmodule) 	();
void	far	pascal	(*sstartplaying)();
void	far	pascal	(*sstopplaying) ();
void	far	pascal	(*sdealloc) 	();
void	far	*sdpoint;

FILE	*fil;
char	*playpoint;
char	*playmem;

word	error;
word	playseg;
word	playsize;
word	temp;
char	modnamn[25];
const int playerloaded = 0;









/**************************************************/
/* Ber anv„ndaren ange vad han har f”r utrustning */
/* input	: XXX                             */
/* output	: XXX                             */
/**************************************************/
void	askinit(void)
{
   if (playerloaded)	(*saskinit) ();
}

/*****************************/
/* Initailiserar spelrutinen */
/* input	: XXX        */
/* output	: XXX        */
/*****************************/
void	initialize (void)
{
   if (playerloaded)	(*sinitialize) ();
}

/****************************************************/
/* laddar in en modul                               */
/* input	: en pekare/str„ng till modulnamnet */
/* output	: XXX                               */
/****************************************************/
void	loadmodule (char modnamn[])
{
   error = 0;
   if (playerloaded)
   {
      _DX	= (longword) modnamn & 0xffff;
      asm	Call sloadmodule
      asm 	Jnc NoError
      asm	Mov error,Ax
      NoError:
   }
}

/**********************/
/* Startar l†ten      */
/* input	: XXX */
/* output	: XXX */
/**********************/
void	startplaying (void)
{
   if ((playerloaded) && !error)	(*sstartplaying) ();
}

/**********************/
/* Stoppar l†ten      */
/* input	: XXX */
/* output	: XXX */
/**********************/
void	stopplaying (void)
{
   if ((playerloaded) && !error)	(*sstopplaying) ();
}

/**********************/
/* Frig”r minne       */
/* input	: XXX */
/* output	: XXX */
/**********************/
void	dealloc (void)
{
   if ((playerloaded) && !error)	(*sdealloc) ();
}


/***********************************************/
/* Laddar in spelrutinen i minnet              */
/* input	: str„ng/pekare till filnamnet */
/* output	: XXX			       */
/***********************************************/
void	loadovl(char fnamn[])
{
   if (playerloaded) return;
   playmem = (void *) calloc (40000, 1);
   // Normaliserar pekaren...
   for (playpoint=playmem; (longword) playpoint%16; (longword) playpoint++);
   (longword) playpoint += ((longword) playpoint & 0xffff) / 16*256*256;
   (longword) playpoint &= 0xffff0000;

   asm{
      Mov  Ax,Word Ptr playpoint+2
      Mov  playseg,Ax
   }
   if ((fil=fopen(fnamn,"rb"))==NULL)
      {printf("ERROR: Can't find overlay file\n"); exit(1);}
   // Reset(F,1);
   // {$I-}
   fread (&temp,2, 1, fil);
   asm{
      Mov Ax,temp
      Mov Word Ptr saskinit,Ax
      Mov Ax,playseg
      Mov Word Ptr saskinit+2,Ax
   }
   fread (&temp, 2, 1, fil);
   asm{
      Mov Ax,temp
      Mov Word Ptr sinitialize,Ax
      Mov Ax,playseg
      Mov Word Ptr sinitialize+2,Ax
   }
   fread (&temp, 2, 1, fil);
   asm{
      Mov Ax,temp
      Mov Word Ptr sloadmodule,Ax
      Mov Ax,playseg
      Mov Word Ptr sloadmodule+2,Ax
   }
   fread (&temp, 2, 1, fil);
   asm{
      Mov Ax,temp
      Mov Word Ptr sstartplaying,Ax
      Mov Ax,playseg
      Mov Word Ptr sstartplaying+2,Ax
   }
   fread (&temp, 2, 1, fil);
   asm{
      Mov Ax,temp
      Mov Word Ptr sstopplaying,Ax
      Mov Ax,playseg
      Mov Word Ptr sstopplaying+2,Ax
   }
   fread (&temp, 2, 1, fil);
   asm{
      Mov Ax,temp
      Mov Word Ptr sdealloc,Ax
      Mov Ax,playseg
      Mov Word Ptr sdealloc+2,Ax
   }
   fread (&temp, 2, 1, fil);
   asm{
      Mov Ax,temp
      Mov Word Ptr sdpoint,Ax
      Mov Ax,playseg
      Mov Word Ptr sdpoint+2,Ax
   }
   for (playsize=0; !feof(fil); fread (&playpoint[playsize++], 1, 1, fil));
   playsize--;
   asm{
      Push Es
      Mov  Es,playseg
      Mov  Cx,playsize
      Shr  Cx,1
      Mov  Bx,0
   }
   UnCode:
   asm{
      Mov  Ax,Es:[Bx]
      Ror  Ax,7
      Xor  Ax,Cx
      Xor  Ax,0x0B32A
      Mov  Es:[Bx],Ax
      Add  Bx,2
      Loop UnCode
      Pop  Es
   }
   // {$I+}
   fclose (fil);
   (int) playerloaded = 1;
}

/**********************************/
/* frig”r minne efter spelrutinen */
/* input	: XXX		  */
/* output	: XXX		  */
/**********************************/
void	removeovl (void)
{
   free (playmem);
   (int) playerloaded = 0;
}

/*****************************************/
/* s„tter volymen till n†got mellan 0-64 */
/* input	: word = ny volym	 */
/* output	. XXX			 */
/*****************************************/
void	mastervolume (unsigned int mastvol)
{
   if (!playerloaded) return;
   asm{
      Push Es
      Mov  Bx,word ptr [sdpoint]
      Mov  Es,word ptr [sdpoint+2]
      Mov  Ax,mastvol
      Mov  Es:[Bx+10],Ax
      Pop Es
   }
}

/*****************************************************************/
/* retunerar 'blinka-i-takt-med-musiken-v„rde' f”r angiven kanal */
/* input	: word = med kanalen (0-3) som skall testas	 */
/* output	: word = ett 'blinka-i-takt-med-musiken-v„rde'	 */
/*****************************************************************/
unsigned int	bopbar (unsigned int barno)
{
   if (!playerloaded)	return 0;
   if ((barno<1) || (barno>4))	return 0;
   temp = barno;
   asm{
      Push Es
      Mov  Bx,word ptr [sdpoint]
      Mov  Es,word ptr [sdpoint+2]
      Mov  Ax,temp
      Shl  Ax,1
      Add  Bx,Ax
      Mov  Ax,Es:[Bx+10]
      Mov  temp,Ax
      Pop Es
   }
   return temp;
}

/**************************************************************************/
/* L†ter anv„ndaren best„mma sin konfiguration utan att anv„nda 'askinit' */
/* input	: word = device, speed. SB dma, SB port, SB port	  */
/* output	: XXX							  */
/**************************************************************************/
void	setsys (unsigned int sdev,
		unsigned int tspeed,
		unsigned int sbdma,
		unsigned int sbirq,
		unsigned int sbport)
{
   if (!playerloaded)	return;
/*   ssdev	= sdev;
   stspeed	= tspeed;
   ssbdma	= sbdma;
   ssbirq	= sbirq;
   ssbport	= sbport;*/
   asm{
      Push Es
      Mov  Bx,word ptr [sdpoint]
      Mov  Es,word ptr [sdpoint+2]

      Mov  Ax,sdev
      Mov  word ptr Es:[BX],Ax
      Mov  Ax,tspeed
      Mov  word ptr Es:[BX+2],Ax
      Mov  Ax,sbdma
      Mov  word ptr Es:[BX+4],Ax
      Mov  Ax,sbirq
      Mov  word ptr Es:[BX+6],Ax
      Mov  Ax,sbport
      Mov  word ptr Es:[BX+8],Ax
      Pop  Es
   }
}
