#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 GetMouse(Point *p) { double xpos, ypos; glfwGetCursorPos(glfwGetCurrentContext(), &xpos, &ypos); p->h = floor(xpos); p->v = floor(ypos); } void GetMouseRel(Point *p) { const auto window = glfwGetCurrentContext(); glfwGetWindowSize(window, &p->h, &p->v); p->h /= 2; p->v /= 2; double xpos, ypos; glfwGetCursorPos(window, &xpos, &ypos); glfwSetCursorPos(window, p->h, p->v); // we shouldn't need this p->h = floor(xpos) - p->h; p->v = floor(ypos) - p->v; } int Button(void) { const auto window = glfwGetCurrentContext(); return glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS; } bool IsKeyDown(int key) { const auto window = glfwGetCurrentContext(); return glfwGetKey(window, key) == GLFW_PRESS; } #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 and load it into OpenAL */ void loadOgg(char *filename, ALuint buffer, ALuint source) { /* Try to find the real file (and place it in filename1) */ char filename1[MAX_PATH]; fix_filename(filename, filename1); FILE* fp = fopen(filename1, "rb"); if (fp == NULL) { fprintf(stderr, "ERROR: unable to open %s\n", filename1); exit(EXIT_FAILURE); } OggVorbis_File vf; int error = -ov_open(fp, &vf, NULL, 0); if (error > 0) { fprintf(stderr, "ERROR: vorbis error %d opening %s\n", error, filename1); exit(EXIT_FAILURE); } vorbis_info* vi = ov_info(&vf, -1); if (vi == NULL) { fprintf(stderr, "ERROR: vorbis error opening %s (ov_info failed)\n", filename1); exit(EXIT_FAILURE); } /* Hack around some possible ogg vorbis weirdness */ ALsizei size = vi->channels * 2 * ov_pcm_total(&vf, -1); ALvoid* data = malloc(((size + 2047) / 2048 + 1) * 2048); if (data == NULL) { fprintf(stderr, "ERROR: could not allocate %d bytes while loading %s\n", size, filename1); exit(EXIT_FAILURE); } char* i = (char*) data; int section; long ret; #if BYTE_ORDER == BIG_ENDIAN while (ret = ov_read(&vf, i, 1024, 1, 2, 1, §ion)) #else while (ret = ov_read(&vf, i, 1024, 0, 2, 1, §ion)) #endif if (ret > 0) /* XXX: How about negative ret? */ i += ret; switch (vi->channels) { case 1: alBufferData(buffer, AL_FORMAT_MONO16, data, size, vi->rate); break; case 2: alBufferData(buffer, AL_FORMAT_STEREO16, data, size, vi->rate); break; default: fprintf(stderr, "ERROR: ogg %s has %d channels\n", filename1, vi->channels); exit(EXIT_FAILURE); } free(data); ov_clear(&vf); alSourcei(source, AL_BUFFER, buffer); }