summary refs log tree commit diff
path: root/src/Support.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Support.cpp')
-rw-r--r--src/Support.cpp386
1 files changed, 386 insertions, 0 deletions
diff --git a/src/Support.cpp b/src/Support.cpp
new file mode 100644
index 0000000..7c77fc5
--- /dev/null
+++ b/src/Support.cpp
@@ -0,0 +1,386 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "SDL/SDL.h"
+
+#include "Support.h"
+#include "Files.h"
+
+int Random()
+{
+#if RAND_MAX >= 65535
+	return (rand() % 65535) - 32767;
+#else
+#error please fix this for your platform
+#endif
+}
+
+void Microseconds(UnsignedWide *microTickCount)
+{
+	/* NOTE: hi isn't used in BS, so it's not implemented here */
+	/* TODO: does game need microsecond precision? */
+	microTickCount->hi = 0;
+	microTickCount->lo = SDL_GetTicks() * 1000;
+}
+
+void GetMouse(Point *p)
+{
+	int x;
+	int y;
+	
+	SDL_GetMouseState(&x, &y);
+	
+	p->h = x;
+	p->v = y;
+}
+
+void GetMouseRel(Point *p)
+{
+	int x;
+	int y;
+	
+	SDL_GetRelativeMouseState(&x, &y);
+	
+	p->h = x;
+	p->v = y;
+}
+int Button(void)
+{
+	return (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(1));
+}
+
+void InitMouse()
+{
+// STUB_FUNCTION;
+}
+
+void MoveMouse(int xcoord, int ycoord, Point *mouseloc)
+{
+	/* TODO: mouse warp is annoying when we can just grab the mouse */
+#ifdef FULLSCREEN
+	SDL_WarpMouse(xcoord, ycoord);
+	SDL_PumpEvents();
+#endif
+	GetMouse(mouseloc);
+}
+
+void DisposeMouse()
+{
+// STUB_FUNCTION;
+}
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifndef MAX_PATH
+#define MAX_PATH 256
+#endif
+
+static int find_filename(char *filename)
+{
+	char *ptr;
+	char *cur;
+	char *next;
+	DIR *dir;
+	struct dirent *dirent;
+	
+	if (access(filename, R_OK) == 0) {
+		return 1;
+	}
+	
+	ptr = filename;
+	
+	while (*ptr) {
+		if (ptr == filename || *ptr == '/') {
+			if (*ptr == '/') {
+				cur = ptr+1;
+			} else {
+				cur = ptr;
+			}
+			
+			if (*cur == 0) {
+				/* hit the end */
+				break;
+			}
+			
+			next = strchr(cur, '/');
+			
+			if (ptr != filename) {
+				*ptr = 0;
+			}
+			
+			if (next) {
+				*next = 0;
+			}
+			
+			if (ptr == filename && *ptr == '/') {
+				dir = opendir("/");
+			} else {
+				dir = opendir(filename);
+			}
+			
+			if (dir == NULL) {
+				if (ptr != filename) {
+					*ptr = '/';
+				}
+				
+				if (next) {
+					*next = 0;
+				}
+				
+				return 0;
+			}
+			
+			while ((dirent = readdir(dir)) != NULL) {
+				if (strcasecmp(cur, dirent->d_name) == 0) {
+					strcpy(cur, dirent->d_name);
+					break;
+				}
+			}
+			
+			closedir(dir);
+			
+			if (ptr != filename) {
+				*ptr = '/';
+			}
+			
+			if (next) {
+				*next = '/';
+				ptr = next;
+			} else {
+				ptr++;
+			}
+		} else {
+			ptr++;
+		}
+	}
+	
+	if (access(filename, R_OK) == 0) {
+		return 1;
+	}
+	
+	return 0;
+}
+
+static void fix_filename(const char *original, char *fixed)
+{
+	const char *start;
+	int i;
+	int len;
+
+	start = original;
+	if (original[0] == ':') {
+		start = &original[1];
+	}
+
+	fixed[MAX_PATH-1] = 0;
+	
+	strncpy(fixed, start, MAX_PATH);
+	
+	/* check to see if strncpy overwrote the terminator */
+	if (fixed[MAX_PATH-1] != 0) {
+		fixed[MAX_PATH-1] = 0;
+	
+		fprintf(stderr, "ERROR: file truncation error: %s -> %s\n", 
+			original, fixed);
+	}
+	
+	len = strlen(fixed);
+	for (i = 0; i < len; i++) {
+		if (fixed[i] == ':') {
+			fixed[i] = '/';
+		}
+	}
+	
+	/* 
+	   here we would try to see if the file is available (game dir),
+	   else try another dir
+	   
+	   really, this function also needs a flag to indicate whether
+	   it should only go to local (write) or both (read)
+	 */
+
+	if (find_filename(fixed) == 0) {
+		fprintf(stderr, "find failed: %s\n", fixed);
+	}
+}
+
+/*
+Convenient Filename Hacks
+*/
+
+FILE *cfh_fopen(const char *filename, const char *mode)
+{
+	char filename1[MAX_PATH];
+	
+	fix_filename(filename, filename1);
+	
+	return fopen(filename1, mode);	
+}
+
+int Files::OpenFile(Str255 Name)
+{
+	char filename1[MAX_PATH];
+	
+	fix_filename((char *)Name, filename1);
+	
+	sFile = open(filename1, O_RDONLY | O_BINARY);
+	return sFile;
+}
+
+void Files::EndLoad()
+{
+	if (sFile != -1) {
+		FSClose( sFile );
+	}
+	
+	sFile = -1;
+}
+
+#ifdef NOOGG    
+/*
+  Our own special magic version that fixes the filename.
+ */
+void alutLoadWAVFile_CFH(char *filename, ALenum *format, void **wave,
+	unsigned int *size, ALsizei *freq)
+{
+	char filename1[MAX_PATH];
+	ALsizei format1, size1, bits1, freq1;
+	
+	fix_filename(filename, filename1);
+	
+	alutLoadWAV(filename1, wave, &format1, &size1, &bits1, &freq1);
+	
+	*format = format1;
+	*size = size1;
+	*freq = freq1;
+}
+
+void alutUnloadWAV_CFH(ALenum format, void *wave, unsigned int size,
+	ALsizei freq)
+{
+	free(wave);
+}
+#else
+#include <vorbis/vorbisfile.h>
+
+/*
+Read the requested OGG file into memory, and extract the information required
+by OpenAL
+*/
+void LoadOGG_CFH(char *filename, ALenum *format, void **wave,
+	unsigned int *size, ALsizei *freq)
+{
+	char filename1[MAX_PATH];
+	ALsizei format1, size1, freq1;
+	void *wave1;
+	OggVorbis_File vf;
+	vorbis_info *vi;
+	FILE *fp;
+	int current_section;
+	char *buf;
+	int asize;
+	int err;
+	int eof;
+
+#if BYTE_ORDER == BIG_ENDIAN
+	const int endian = 1;
+#else
+	const int endian = 0;
+#endif
+
+	/* try to find the real file (and place it in filename1) */
+	fix_filename(filename, filename1);
+
+	/* open it for reading */
+	fp = fopen(filename1, "rb");
+	if (fp == NULL) {
+		fprintf(stderr, "ERROR: unable to open %s\n", filename1);
+		exit(EXIT_FAILURE);
+	}
+	
+	/* open it up */
+	err = ov_open(fp, &vf, NULL, 0);	
+	if (err < 0) {
+		fprintf(stderr, "ERROR: vorbis error %d opening %s\n", -err, filename1);
+		exit(EXIT_FAILURE);
+	}
+
+	/* get the ogg information */
+	vi = ov_info(&vf, -1);
+	if (vi == NULL) {
+		fprintf(stderr, "ERROR: vorbis error opening %s (ov_info failed)\n", filename1);
+		exit(EXIT_FAILURE);
+	}
+	
+	/* calculate the byte size */
+	size1 = vi->channels * 2 * ov_pcm_total(&vf, -1);
+
+	/* hack around some possible ogg vorbis weirdness */
+	asize = ((size1 + 2047) / 2048 + 1) * 2048;
+	
+	/* allocate our buffer */	
+	wave1 = malloc(asize);
+	
+	if (wave1 == NULL) {
+		fprintf(stderr, "ERROR: could not allocate %d bytes while loading %s\n", size1, filename1);
+		exit(EXIT_FAILURE);
+	}
+
+	/* read it in */
+	eof = 0;
+	buf = (char *)wave1;
+	
+	while(!eof) {
+		long ret = ov_read(&vf, buf, 1024, endian, 2, 1, 
+			&current_section);
+		
+		if (ret == 0) {
+			/* end of file */
+			eof = 1;
+		} else if (ret < 0) {
+			/* some sort of error */
+			
+			/* TODO: is this ok to ignore? */
+		} else {
+			buf += ret;
+		}
+	}
+
+	/* get the rest of the information */
+	if (vi->channels == 1) {
+		format1 = AL_FORMAT_MONO16;
+	} else if (vi->channels == 2) {
+		format1 = AL_FORMAT_STEREO16;
+	} else {
+		fprintf(stderr, "ERROR: ogg %s has %d channels\n", filename1, vi->channels);
+		exit(EXIT_FAILURE);
+	}
+	
+	freq1 = vi->rate;
+
+	/* we are done with the ogg, so free it */
+	ov_clear(&vf);
+	
+	/* finall, give the values to the caller */	
+	*format = format1;
+	*size = size1;
+	*freq = freq1;
+	*wave = wave1;
+}
+
+/*
+Free the OGG buffer
+*/
+void FreeOGG(ALenum format, void *wave, unsigned int size,
+	ALsizei freq)
+{
+	free(wave);
+}
+#endif