#include #include #include #include #include #include #include #include #include #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; } /* 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, ¤t_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); }