#ifdef TARGET_DOS

#include <allegro.h>

BEGIN_GFX_DRIVER_LIST
END_GFX_DRIVER_LIST
BEGIN_COLOR_DEPTH_LIST
END_COLOR_DEPTH_LIST
BEGIN_JOYSTICK_DRIVER_LIST
END_JOYSTICK_DRIVER_LIST

AUDIOSTREAM *outstr;

bool begin_sound_card(int freq, int bufsize)
{
	allegro_init();
	install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL);
	outstr = play_audio_stream(bufsize, 8, 0, freq, 255, 127);
	return outstr != NULL;
}

void end_sound_card(void)
{
	stop_audio_stream(outstr);
}

unsigned char *get_next_pointer_card(void)
{
	unsigned char *sndbuf;
	while(! (sndbuf = (unsigned char *)get_audio_stream_buffer(outstr)));
	return sndbuf;
}

void done_with_pointer_card(void)
{
	free_audio_stream_buffer(outstr);
}

#endif

#include <stdio.h>
#include <malloc.h>
FILE *outraw;
unsigned char *tmp;
int bufs;

bool begin_sound_file(int freq, int bufsize)
{
	printf("Writing a %dHz, 8bit, mono, unsigned RAW file named \"sound.raw\"\n", freq);
	outraw = fopen("sound.raw", "wb");
	bufs = bufsize;
	tmp = (unsigned char *)malloc(bufsize);
	return true;
}

void end_sound_file(void)
{
	fclose(outraw);
	free(tmp);
}

unsigned char *get_next_pointer_file(void)
{
	return tmp;
}

void done_with_pointer_file(void)
{
	fwrite(tmp, 1, bufs, outraw);
}

#ifdef TARGET_WIN
#include <windows.h>

HWAVEOUT device;
volatile WAVEHDR block1, block2, *cblock;
volatile unsigned char *data1, *data2;

bool begin_sound_card(int freq, int bufsize)
{
	WAVEFORMATEX format;

	format.wFormatTag = WAVE_FORMAT_PCM;
	format.nChannels = 1;
	format.nSamplesPerSec = freq;
	format.nAvgBytesPerSec = freq;
	format.nBlockAlign = 1;
	format.wBitsPerSample = 8;
	format.cbSize = 0;

	data1 = data2 = NULL;

	if(waveOutOpen(&device, WAVE_MAPPER, &format, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR)
		return false;

	/* prepare header 1 */
	data1 = (volatile unsigned char *)malloc(bufsize);
	if(!data1)
		return false;

	block1.lpData = (char *)data1;
	block1.dwBufferLength = bufsize;
	block1.dwFlags = 0;

	if(waveOutPrepareHeader(device, (WAVEHDR *)&block1, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
	{
		free((char *)data1); data1 = NULL;
		return false;
	}

	/* prepare header 2 */
	data2 = (volatile unsigned char *)malloc(bufsize);
	if(!data2)
		return false;

	block2.lpData = (char *)data2;
	block2.dwBufferLength = bufsize;
	block2.dwFlags = 0;

	if(waveOutPrepareHeader(device, (WAVEHDR *)&block2, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
	{
		free((char *)data2); data2 = NULL;
		return false;
	}

	/* finish */
	memset((char *)data1, 127, bufsize);
	memset((char *)data2, 127, bufsize);

	waveOutWrite(device, (WAVEHDR *)&block2, sizeof(WAVEHDR));
	cblock = &block1;

	return true;
}

void end_sound_card(void)
{
	if(data1)
	{
		waveOutUnprepareHeader(device, (WAVEHDR *)&block1, sizeof(WAVEHDR));
		free((char *)data1);
	}

	if(data2)
	{
		waveOutUnprepareHeader(device, (WAVEHDR *)&block2, sizeof(WAVEHDR));
		free((char *)data2);
	}

	waveOutClose(device);
}

unsigned char *get_next_pointer_card(void)
{
	return (unsigned char *)cblock->lpData;
}

void done_with_pointer_card(void)
{
	volatile WAVEHDR *next;

	next = (cblock == &block1) ? &block2 : &block1;

	waveOutWrite(device, (WAVEHDR *)cblock, sizeof(WAVEHDR));
	while(!(next->dwFlags&WHDR_DONE));

	cblock = next;
}

#endif

#ifdef TARGET_OSS

#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/soundcard.h>

int audio_fd;
int bufsize;
unsigned char *audio_buffer;

bool begin_sound_card(int freq, int b)
{
	int speed = 44100;
	int *sigs;

	bufsize = b;

	if((audio_fd = open("/dev/dsp", O_WRONLY, 0)) == -1)
		return false;

	if(ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed) == -1)
	{
		close(audio_fd);
		return false;
	}

	if(abs(speed-44100) > 2205)
	{
		close(audio_fd);
		return false;
	}

	audio_buffer = (unsigned char *)calloc(bufsize, 1);

	return true;
}

void end_sound_card(void)
{
	free(audio_buffer);
	close(audio_fd);
}

unsigned char *get_next_pointer_card(void)
{
	return audio_buffer;
}

void done_with_pointer_card(void)
{
	while(!write(audio_fd, audio_buffer, bufsize));
}

#endif
