//** LOADER ->	DIGPAK and MIDPAK dynamic loader.
//**						Include this header file to support dynamic loading of
//**						the real-mode DIGPAK and MIDPAK drivers.	If you only
//**						want DIGPAK suppor then set MIDPAK_LOADER to false, if
//**						you just want MIDPAK support then set DIGPAK_LOADER to false.
//**						Requires: SUPPORT.C SUPPORT.H  basic file i/o memory managment.
//**											VECTOR.ASM VECTOR.H  Hook and unhook the realmode
//**											VECTOR.COM					 vector manager, VECTOR.COM.
//**											DOSCALLS.ASM DOSCALLS.H, real-mode 1mb memory
//**																					 allocation and management.
//**											DIGPLAY.ASM DIGPLAY.H DigPak API link layer.
//**											MIDPAK.ASM MIDPAK.H  MidPak API link layer.
//**											STDIO.H STDLIB.H	C standard file support functions.
/*																																					 */
/*		Written by John W. Ratcliff (c) 1994																	 */
/*			 Compuserve: 70253,3237 																						 */
/*			 Genie: J.RATCLIFF3 																								 */
/*			 BBS: 1-314-939-0200																								 */
/*			 Addresss:																													 */
/*					 747 Napa Lane																									 */
/*					 St. Charles, MO 63304																					 */
/*																																					 */
#include <stdio.h>
#include <stdlib.h>

#include "loader.h"  // loader prototypes.
#include "support.h" // Include header file for access to common DOS routines.
#include "vector.h"

#if DIGPAK_LOADER
#include "digplay.h" // Include header for DIGPAK functions.
static int	HaveDigPak=0; // True if DigPak driver currently loaded.
static int	DigPakOn=0; 	// True if loaded DigPak driver is initialized.
static char *DigPakLoad=0; // DigPak Load address.
static int DIGPAKTSR=0; // DigPak resident as a TSR.
#endif
#if MIDPAK_LOADER
#include "midpak.h"  // Include header for MIDPAK functions.
static int HaveMidPak=0; // True if MidPak driver is loaded.
static int MidPakOn=0;	 // True if MidPak driver is initialized.
static char *MidPakLoad=0; // MidPak load address.
static char *MidPakAdv;  // MidPak ADV driver.
static char *MidPakAd;	 // MidPak AD file.
static int MIDPAKTSR=0;  // MidPak resident as a TSR
#endif

static char *vector=0;
int StartVector(void);

#if DIGPAK_LOADER
int LoadDigPak(char *fname)
{
	long int siz;

	if ( HaveDigPak ) return(0); // DigPak is allready loaded, trying to load it twice!
	if ( CheckIn() )
	{
		DIGPAKTSR = 1;
		HaveDigPak = 1;
		#if MIDPAK_LOADER
		if ( !CheckMidiIn() )  // MIDPAK must be loaded resident if DIGPAK
		{ 										 // have been loaded resident.
			DIGPAKTSR = 0;
			HaveDigPak = 0;
			return(0);
		}
		#endif
		return(1);
	}
	DigPakLoad = floadlow(fname,&siz);
	if ( DigPakLoad )
	{
		HaveDigPak = 1; // driver was loaded. not yet initialized though.
	}
	return(HaveDigPak);
}

int InitDigPak(void)
{
	int bad = 0;

	if ( HaveDigPak )
	{
		if ( DIGPAKTSR )
			DigPakOn = 1;
		else
		{
			if ( StartVector() ) // Bootstrap vector.
				DigPakOn = InitDP(DigPakLoad);
			else
				DigPakOn = 0;
		}
	}
	if ( DigPakOn )
	{
		if ( ReportVersionNumber() < 340 ) bad = 1; // Version number too old.
		if ( AudioCapabilities() & USESTIMER ) bad = 2; // We don't support timer based drivers.
		if ( bad )
			DeInitDigPak();
		else
			SetDPMIMode(1);
	}
	return(DigPakOn);
}

int DeInitDigPak(void)
{
	if ( DigPakOn )
	{
		SetDPMIMode(0);
		if ( DIGPAKTSR )
			DIGPAKTSR = 0;
		else
			DeInitDP(DigPakLoad);
		DigPakOn = 0;
		return(1);
	}
	return(0);
}

int UnLoadDigPak(void)
{
	if ( HaveDigPak )
	{
		if ( DigPakOn ) DeInitDigPak();
		if ( DigPakLoad ) realfree(DigPakLoad);
		DigPakLoad = 0;
		HaveDigPak = 0;
		return(1);
	}
	return(0);
}
#endif

#if MIDPAK_LOADER
int LoadMidPak(char *fname,char *adv,char *ad)
{
	long int siz;

	if ( HaveMidPak ) return(0); // MidPak is allready loaded, trying to load it twice!
	if ( CheckMidiIn() )
	{
		MIDPAKTSR = 1;
		HaveMidPak = 1;
		return(1);
	}
	MidPakLoad = floadlow(fname,&siz);
	if ( MidPakLoad )
	{
		MidPakAdv = floadlow(adv,&siz);
		if ( !MidPakAdv )
		{
			realfree(MidPakLoad);
			MidPakLoad = 0;
			return(0);
		}
		if ( ad )
		{
			MidPakAd = floadlow(ad,&siz);
			if ( !MidPakAd )
			{
				realfree(MidPakAdv);
				realfree(MidPakLoad);
				MidPakLoad = 0;
				return(0);
			}
		}
		else
			MidPakAd = 0;
		HaveMidPak = 1; // driver was loaded. not yet initialized though.
	}
	return(HaveMidPak);
}

int InitMidPak(void)
{
	int ret;

	if ( HaveMidPak )
	{
		if ( MIDPAKTSR )
			MidPakOn = 1;
		else
		{
			if ( StartVector() ) // Bootstrap vector manager.
			{
				ret = InitMP(MidPakLoad,MidPakAdv,MidPakAd);
				if ( ret )
					MidPakOn = 0;
				else
					MidPakOn = 1;
			}
			else
				MidPakOn = 0;
		}
	}
	return(MidPakOn);
}

int DeInitMidPak(void)
{
	if ( MidPakOn )
	{
		MidiStop(); // Stop any playing midi sequence
		if ( MIDPAKTSR )
			MIDPAKTSR = 0;
		else
			DeInitMP(MidPakLoad);
		MidPakOn = 0;
		return(1);
	}
	return(0);
}

int UnLoadMidPak(void)
{
	if ( HaveMidPak )
	{
		if ( MidPakOn ) DeInitMidPak();
		if ( MidPakLoad )
		{
			if ( MidPakAd ) realfree(MidPakAd);
			realfree(MidPakAdv);
			realfree(MidPakLoad);
		}
		MidPakLoad = 0;
		HaveMidPak = 0;
		return(1);
	}
	return(0);
}
#endif

// Install vector manager if not allready installed.
int StartVector(void)
{
	long int siz;

	if ( !vector )
	{
		vector = floadlow("VECTOR.COM", &siz);
		if ( vector )
		{
			if ( !InstallVector(vector) )
			{
				realfree(vector);
				vector = 0;
			}
		}
	}
	if ( vector )
		return(1);
	else
		return(0);
}

void RemoveVectorLoader(void)
{
	if ( vector )
	{
		realfree(vector);
		vector = 0;
		RemoveVector();
	}
}
