/***************************************************************************
*	NAME:  PLAY3DI.C
**
**	Copyright (C) 1992,1993 by Focal Point 3D Audio and FORTE 
**                All Rights Reserved
**
**       "This software is furnished under a license and may be used,
**       copied, or disclosed only in accordance with the terms of such
**       license and with the inclusion of the above copyright notice.
**       This software or any other copies thereof may not be provided or
**       otherwise made available to any other person. No title to and
**       ownership of the software is hereby transfered."
****************************************************************************
*  CREATION DATE: 11/18/92
*--------------------------------------------------------------------------*
*     VERSION	DATE	   NAME		DESCRIPTION
*>	1.0	05/01/93		Original
***************************************************************************/


/*********************************************************************
 *
 * Example program for playing a 3D Sound track
 *
 *********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <math.h>
#include <alloc.h>

#include "forte.h"
#include "gf1proto.h"
#include "extern.h"
#include "ultraerr.h"

#include "threed.h"
#include "hdr3d.h"

/* Caution: Don't make BSIZE too small. It won't be able to feed */
/* data to the UltraSound fast enough .... */
#define BSIZE 30*1024
#define ULTRA_BSIZE (long)(128L*1024L)

/* Joystick stuff */
int center_x=0;
int right_x=0;
int left_x=1000;
int center_z=0;
int fwrd_z=1000;
int back_z=0;

void
usage()
{
	printf("\nUsage: play3di filename\n");
}

/* This function will load DRAM with the next data in the file */
unsigned long
load_dram(fp,sound,dramloc,dramsize,pcsize,pcbuffer)
FILE *fp;					/* File pointer */
SOUND_3D far *sound;			/* 3d sound handle */
unsigned long dramloc;		/* Where to put it */
unsigned long dramsize;		/* How much to read & transfer */
unsigned int pcsize;		/* How big is the PC buffer for DMA */
void far *pcbuffer;			/* pointer to pc DMA buffer */
{
int i;
unsigned int length;
unsigned long total=0L;
int num;
int remaining;

num = dramsize / (long)pcsize;
remaining = dramsize - (long)((long)pcsize*(long)num);

/* Send as many full buffers as possible */
for (i=0;i<num;i++)
	{
	length = fread(pcbuffer,1,pcsize,fp);
	if (length == pcsize)
		{
		UltraDownload(pcbuffer,sound->dmode,dramloc,length,TRUE);
		dramloc += length;
		total += length;
		}
	else
		break;
	}

/* Send amount left over */
if (remaining != 0)
	{
	length = fread(pcbuffer,1,remaining,fp);
	if (length == remaining)
		{
		UltraDownload(pcbuffer,sound->dmode,dramloc,length,TRUE);
		dramloc += length;
		total += length;
		}
	}

return(total);
}

void
main(argc,argv)
int argc;
char *argv[];
{
FILE *fp;
int i;
int	key_char;
int	done;
ULTRA_CFG 	config;
SOUND_3D	sound_3d;
void far 	*buffer;
int val;
int new_xpos,new_zpos;
int last_x,last_z;
unsigned int temp_it;
char	filename[80];
int 	x_pos,z_pos,x_pos2,z_pos2,buttons;
unsigned long memloc;
unsigned long middle;
unsigned long where;
unsigned long length;
int first_buff = TRUE;
int first_track;

if (argc < 2)
	{
	usage();
	printf("\nYou need to specify a file to play.\n");
	exit(-1);
	}

strcpy(filename,argv[argc-1]);

fp = fopen(filename,"rb");
if (fp == NULL)
	{
	printf("Unable to open %s\n",filename);
	exit(-1);
	}

/* Get the ULTRASND environment string parameters */
UltraGetCfg(&config);

if (UltraProbe(config.base_port) == NO_ULTRA)
	{
	printf("No card found\n");
	exit(-1);
	}

if (UltraOpen(&config,28) == NO_ULTRA)
	{
	printf("No card found\n");
	exit(-1);
	}

/* allocate memory in PC AND UltraSound */
buffer = malloc((unsigned int)BSIZE);
if (buffer == NULL)
	{
	printf("Unable to get PC memory\n");
	goto done1;
	}

val = UltraSetup3dInterleave(&sound_3d,filename,(long)ULTRA_BSIZE);
if (val != ULTRA_OK)
	{
	printf("Couldn't load 3d interleaved sound file. Err code %d\n",val);
	goto failure;
	}

/* Now prime the buffer with data from file */
fseek(fp,(long)sizeof(FILEHDR_3D),0);

for (i=0;i<6;i++)
	{
	if (sound_3d.vdata[i].voicenum != -1)
		{
		first_track = sound_3d.vdata[i].voicenum;
		memloc = sound_3d.vdata[i].start;
		break;
		}
	}

middle = memloc + ULTRA_BSIZE/2L;

/* Prime the buffer with data */
length = load_dram(fp,&sound_3d,memloc,ULTRA_BSIZE,BSIZE,buffer);
if (length != ULTRA_BSIZE)
	{
	printf("Not enough data\n");
	goto done1;
	}

UltraEnableOutput();

read_joystick(&x_pos,&z_pos,&x_pos2,&z_pos2,&buttons);
last_x = left_x = right_x = center_x = x_pos;
last_z = fwrd_z = back_z = center_z = z_pos;

/* Start the sound */
UltraStart3d(&sound_3d);
where = memloc;

done = FALSE;

while (!done)
	{
	if( fast_kbhit() )	/* Exit when a key is hit */
		{
		key_char = getch();		/* read the character */
		done = TRUE;
		break;
		}

	read_joystick(&x_pos,&z_pos,&x_pos2,&z_pos2,&buttons);
	if (x_pos < center_x )
		{
		if (x_pos < left_x)
			left_x = x_pos;
		}
	else
		{
		if (x_pos > right_x)
			right_x = x_pos;
		}

	if (z_pos < center_z )
		{
		if (z_pos < fwrd_z)
			fwrd_z = z_pos;
		}
	else
		{
		if (z_pos > back_z)
			back_z = z_pos;
		}

	new_xpos = 0;
	new_zpos = 0;
	temp_it = abs((x_pos - center_x))<<8;
	if (x_pos > center_x)
		{
		new_xpos = temp_it/(right_x-center_x+1);
		}
	else
		{
		new_xpos = -1*(temp_it/(center_x-left_x+1));
		}

	temp_it = abs(z_pos - center_z)<<8;
	if (z_pos > center_z)
		{
		new_zpos = -1*(temp_it/(back_z-center_z+1));
		}
	else
		{
		new_zpos = temp_it/(center_z-fwrd_z+1);
		}

	printf("%03d %03d       \r",new_xpos,new_zpos);

	if ((abs(new_xpos-last_x) > 3) || (abs(new_zpos-last_z) > 3))
		UltraAbsPosition3d(&sound_3d,new_xpos,0,new_zpos);

	last_x = new_xpos;
	last_z = new_zpos;

	if (!(buttons & 0x10))
		{
		UltraStart3d(&sound_3d);
		}

	/* See if we need more data */
	where = UltraReadVoice(first_track);
	/* Are we waiting for first half to finish playing ? */
	if (first_buff)	/* yes */
		{
		if (where > middle)
			{
			/* fill in first half */
			length = load_dram(fp,&sound_3d,memloc,ULTRA_BSIZE/2L,BSIZE,buffer);
			if (length != ULTRA_BSIZE/2L)
				{
				done = TRUE;
				}
			first_buff = FALSE;	/* now looking at second buff */
			}
		}
	else		/* how about second */
		{
		if (where < middle)	/* has it looped back to beginning? */
			{
			/* fill in second half ... */
			length = load_dram(fp,&sound_3d,middle,ULTRA_BSIZE/2L,BSIZE,buffer);
			if (length != ULTRA_BSIZE/2L)
				{
				done = TRUE;
				}
			first_buff = TRUE;	/* now looking at second buff */
			}
		}
	}


/* Stop the sound */
UltraStop3d(&sound_3d,FALSE);

/* Free up resources */
UltraRelease3dInterleave(&sound_3d);

failure:
	free(buffer);

done1:
	/* close 3D sound track */
	fclose(fp);
	/* Shut sound down & re-init hardware ... */
	UltraClose();
}

