1 /*
2 * Support.cpp
3 * Copyright (C) 2007 by Bryan Duff <duff0097@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/types.h>
23 #include <dirent.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27
28 #include "SDL.h"
29
30 #include "Support.h"
31 #include "Files.h"
32 #include "Config.h"
33
34 extern Config config;
35
Random()36 int Random()
37 {
38 #if RAND_MAX >= 65535
39 return (rand() % 65535) - 32767;
40 #else
41 #error please fix this for your platform
42 #endif
43 }
44
Microseconds(UnsignedWide * microTickCount)45 void Microseconds(UnsignedWide * microTickCount)
46 {
47 /* NOTE: hi isn't used in BS, so it's not implemented here */
48 /* TODO: does game need microsecond precision? */
49 microTickCount->hi = 0;
50 microTickCount->lo = SDL_GetTicks() * 1000;
51 }
52
GetMouse(Point * p)53 void GetMouse(Point * p)
54 {
55 int x;
56 int y;
57
58 SDL_GetMouseState(&x, &y);
59
60 p->h = x;
61 p->v = y;
62 }
63
GetMouseRel(Point * p)64 void GetMouseRel(Point * p)
65 {
66 int x;
67 int y;
68
69 SDL_GetRelativeMouseState(&x, &y);
70
71 p->h = x;
72 p->v = y;
73 }
74
75 // Mouse button click: Left 1, right 2
ButtonClick(int button)76 int ButtonClick(int button)
77 {
78 return (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(button));
79 }
80
InitMouse()81 void InitMouse()
82 {
83 // STUB_FUNCTION;
84 }
85
MoveMouse(int xcoord,int ycoord,Point * mouseloc)86 void MoveMouse(int xcoord, int ycoord, Point * mouseloc)
87 {
88 /* TODO: mouse warp is annoying when we can just grab the mouse */
89 if(config.fullscreen) {
90 SDL_WarpMouse(xcoord, ycoord);
91 SDL_PumpEvents();
92 }
93 GetMouse(mouseloc);
94 }
95
DisposeMouse()96 void DisposeMouse()
97 {
98 // STUB_FUNCTION;
99 }
100
101 #ifndef O_BINARY
102 #define O_BINARY 0
103 #endif
104
105 #ifndef MAX_PATH
106 #define MAX_PATH 256
107 #endif
108
find_filename(char * filename)109 static int find_filename(char *filename)
110 {
111 char *ptr;
112 char *cur;
113 char *next;
114 DIR *dir;
115 struct dirent *dirent;
116
117 if(access(filename, R_OK) == 0) {
118 return 1;
119 }
120
121 ptr = filename;
122
123 while(*ptr) {
124 if(ptr == filename || *ptr == '/') {
125 if(*ptr == '/') {
126 cur = ptr + 1;
127 } else {
128 cur = ptr;
129 }
130
131 if(*cur == 0) {
132 /* hit the end */
133 break;
134 }
135
136 next = strchr(cur, '/');
137
138 if(ptr != filename) {
139 *ptr = 0;
140 }
141
142 if(next) {
143 *next = 0;
144 }
145
146 if(ptr == filename && *ptr == '/') {
147 dir = opendir("/");
148 } else {
149 dir = opendir(filename);
150 }
151
152 if(dir == NULL) {
153 if(ptr != filename) {
154 *ptr = '/';
155 }
156
157 if(next) {
158 *next = 0;
159 }
160
161 return 0;
162 }
163
164 while((dirent = readdir(dir)) != NULL) {
165 if(strcasecmp(cur, dirent->d_name) == 0) {
166 strcpy(cur, dirent->d_name);
167 break;
168 }
169 }
170
171 closedir(dir);
172
173 if(ptr != filename) {
174 *ptr = '/';
175 }
176
177 if(next) {
178 *next = '/';
179 ptr = next;
180 } else {
181 ptr++;
182 }
183 } else {
184 ptr++;
185 }
186 }
187
188 if(access(filename, R_OK) == 0) {
189 return 1;
190 }
191
192 return 0;
193 }
194
195 //FIXME: help!
fix_filename(const char * original,char * fixed)196 static void fix_filename(const char *original, char *fixed)
197 {
198 const char *start;
199 int i;
200 int len;
201
202 start = original;
203 if(original[0] == ':') {
204 start = &original[1];
205 }
206
207 fixed[MAX_PATH - 1] = 0;
208
209 strncpy(fixed, start, MAX_PATH);
210
211 /* check to see if strncpy overwrote the terminator */
212 if(fixed[MAX_PATH - 1] != 0) {
213 fixed[MAX_PATH - 1] = 0;
214
215 fprintf(stderr, "ERROR: file truncation error: %s -> %s\n",
216 original, fixed);
217 }
218
219 len = strlen(fixed);
220 for(i = 0; i < len; i++) {
221 if(fixed[i] == ':') {
222 fixed[i] = '/';
223 }
224 }
225
226 /*
227 here we would try to see if the file is available (game dir),
228 else try another dir
229
230 really, this function also needs a flag to indicate whether
231 it should only go to local (write) or both (read)
232 */
233
234 if(find_filename(fixed) == 0) {
235 fprintf(stderr, "find failed: %s\n", fixed);
236 }
237 }
238
239 /*
240 Convenient Filename Hacks
241 */
cfh_fopen(const char * filename,const char * mode)242 FILE *cfh_fopen(const char *filename, const char *mode)
243 {
244 char filename1[MAX_PATH];
245
246 fix_filename(filename, filename1);
247
248 return fopen(filename1, mode);
249 }
250
OpenFile(Str255 Name)251 int Files::OpenFile(Str255 Name)
252 {
253 char filename1[MAX_PATH];
254
255 fix_filename((char *)Name, filename1);
256
257 sFile = open(filename1, O_RDONLY | O_BINARY);
258 return sFile;
259 }
260
EndLoad()261 void Files::EndLoad()
262 {
263 if(sFile != -1) {
264 FSClose(sFile);
265 }
266
267 sFile = -1;
268 }
269
270 #ifdef NOOGG
271 /*
272 Our own special magic version that fixes the filename.
273 */
alutLoadWAVFile_CFH(char * filename,ALenum * format,void ** wave,unsigned int * size,ALsizei * freq)274 void alutLoadWAVFile_CFH(char *filename, ALenum * format, void **wave,
275 unsigned int *size, ALsizei * freq)
276 {
277 char filename1[MAX_PATH];
278 ALsizei format1, size1, bits1, freq1;
279
280 fix_filename(filename, filename1);
281
282 alutLoadWAV(filename1, wave, &format1, &size1, &bits1, &freq1);
283
284 *format = format1;
285 *size = size1;
286 *freq = freq1;
287 }
288
alutUnloadWAV_CFH(ALenum format,void * wave,unsigned int size,ALsizei freq)289 void alutUnloadWAV_CFH(ALenum format, void *wave, unsigned int size,
290 ALsizei freq)
291 {
292 free(wave);
293 }
294 #else
295 #include <vorbis/vorbisfile.h>
296
297 /*
298 Read the requested OGG file into memory, and extract the information required
299 by OpenAL
300 */
LoadOGG_CFH(char * filename,ALenum * format,void ** wave,unsigned int * size,ALsizei * freq)301 void LoadOGG_CFH(char *filename, ALenum * format, void **wave,
302 unsigned int *size, ALsizei * freq)
303 {
304 char filename1[MAX_PATH];
305 ALsizei format1, size1, freq1;
306 void *wave1;
307 OggVorbis_File vf;
308 vorbis_info *vi;
309 FILE *fp;
310 int current_section;
311 char *buf;
312 int asize;
313 int err;
314 int eof;
315
316 #if BYTE_ORDER == BIG_ENDIAN
317 const int endian = 1;
318 #else
319 const int endian = 0;
320 #endif
321
322 /* try to find the real file (and place it in filename1) */
323 fix_filename(filename, filename1);
324
325 /* open it for reading */
326 fp = fopen(filename1, "rb");
327 if(fp == NULL) {
328 fprintf(stderr, "ERROR: unable to open %s\n", filename1);
329 exit(EXIT_FAILURE);
330 }
331
332 /* open it up */
333 err = ov_open(fp, &vf, NULL, 0);
334 if(err < 0) {
335 fprintf(stderr, "ERROR: vorbis error %d opening %s\n", -err, filename1);
336 exit(EXIT_FAILURE);
337 }
338
339 /* get the ogg information */
340 vi = ov_info(&vf, -1);
341 if(vi == NULL) {
342 fprintf(stderr, "ERROR: vorbis error opening %s (ov_info failed)\n",
343 filename1);
344 exit(EXIT_FAILURE);
345 }
346
347 /* calculate the byte size */
348 size1 = vi->channels * 2 * ov_pcm_total(&vf, -1);
349
350 /* hack around some possible ogg vorbis weirdness */
351 asize = ((size1 + 2047) / 2048 + 1) * 2048;
352
353 /* allocate our buffer */
354 wave1 = malloc(asize);
355
356 if(wave1 == NULL) {
357 fprintf(stderr, "ERROR: could not allocate %d bytes while loading %s\n",
358 size1, filename1);
359 exit(EXIT_FAILURE);
360 }
361
362 /* read it in */
363 eof = 0;
364 buf = (char *)wave1;
365
366 while(!eof) {
367 long ret = ov_read(&vf, buf, 1024, endian, 2, 1,
368 ¤t_section);
369
370 if(ret == 0) {
371 /* end of file */
372 eof = 1;
373 } else if(ret < 0) {
374 /* some sort of error */
375
376 /* TODO: is this ok to ignore? */
377 } else {
378 buf += ret;
379 }
380 }
381
382 /* get the rest of the information */
383 if(vi->channels == 1) {
384 format1 = AL_FORMAT_MONO16;
385 } else if(vi->channels == 2) {
386 format1 = AL_FORMAT_STEREO16;
387 } else {
388 fprintf(stderr, "ERROR: ogg %s has %d channels\n", filename1, vi->channels);
389 exit(EXIT_FAILURE);
390 }
391
392 freq1 = vi->rate;
393
394 /* we are done with the ogg, so free it */
395 ov_clear(&vf);
396
397 /* finall, give the values to the caller */
398 *format = format1;
399 *size = size1;
400 *freq = freq1;
401 *wave = wave1;
402 }
403
404 /*
405 Free the OGG buffer
406 */
FreeOGG(ALenum format,void * wave,unsigned int size,ALsizei freq)407 void FreeOGG(ALenum format, void *wave, unsigned int size, ALsizei freq)
408 {
409 free(wave);
410 }
411 #endif
412