sound control moved to GVAR
[awish.git] / src / gameglobals.c
blob446b00949cda1dcc0d5cad7d34fb20226a556d93
1 /*
2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation, either version 3 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #ifndef AWISH_NO_SOUND
16 # include "SDL_mixer.h"
17 #endif
19 #include "video.h"
20 #include "polymod.h"
22 #include "gameglobals.h"
25 ////////////////////////////////////////////////////////////////////////////////
26 ResFile resfile;
27 ResFile sndfile;
29 SDL_Surface *backs[9];
30 SpriteBank banks[257];
32 //int disableSound = 0;
34 extern int goobers;
37 int mouseX = 0;
38 int mouseY = 0;
39 int mouseButtons = 0;
40 int mouseVisible = 1;
44 #define SOUND_DISABLED (vmGVars[GVAR_SOUND_DISABLED]!=0)
47 ////////////////////////////////////////////////////////////////////////////////
48 __attribute__((__noreturn__)) __attribute__((format(printf, 1, 2))) void fatal (const char *fmt, ...) {
49 va_list ap;
51 fprintf(stderr, "AWISH FATAL: ");
52 va_start(ap, fmt);
53 vfprintf(stderr, fmt, ap);
54 va_end(ap);
55 fprintf(stderr, "\n");
56 exit(1);
60 ////////////////////////////////////////////////////////////////////////////////
61 // These values are not magical, just the default values Marsaglia used.
62 // Any pair of unsigned integers should be fine.
63 #define DEFAULT_M_W (521288629LL)
64 #define DEFAULT_M_Z (362436069LL)
66 static Uint32 m_w = DEFAULT_M_W;
67 static Uint32 m_z = DEFAULT_M_Z;
70 Uint32 getSeedH (void) {
71 return m_z;
75 Uint32 getSeedL (void) {
76 return m_w;
80 Uint32 getSeed (void) {
81 return m_w;
85 /* from system time: long x = dt.ToFileTime(); SetSeed((uint)(x >> 16), (uint)(x % 4294967296)); */
86 void setSeedH (Uint32 u) {
87 m_z = u ? u : DEFAULT_M_Z;
91 void setSeedL (Uint32 u) {
92 m_w = u ? u : DEFAULT_M_W;
96 void setSeedHL (Uint32 h, Uint32 l) {
97 setSeedH(h);
98 setSeedL(l);
102 void setSeed (Uint32 u) {
103 setSeedHL(0, u);
107 Uint32 randUInt32 (void) {
108 Uint32 res;
110 m_z = 36969*(m_z&65535)+(m_z>>16);
111 m_w = 18000*(m_w&65535)+(m_w>>16);
112 res = (m_z<<16)+m_w;
113 if (m_w == 0) m_w = DEFAULT_M_Z;
114 if (m_z == 0) m_z = DEFAULT_M_Z;
115 return res;
119 // the magic number below is 1/(2^32 + 2)
120 // uniform: (randUInt32()+1.0)*2.328306435454494e-10;
121 // the result is strictly between 0 and 1.
124 ////////////////////////////////////////////////////////////////////////////////
125 // return vm code size
126 int loadCodeFile (ResFile *resfile, int pc, int idx, int asmodule) {
127 int rsz = 0, res = 0;
128 uint8_t *buf = loadResFile(resfile, idx, &rsz);
130 if (buf == NULL) return -1;
132 res = vmLoadCodeFileFromDump(buf, rsz, pc, vmMaxGVar, vmMaxTVar, asmodule?NULL:&vmMaxGVar, asmodule?NULL:&vmMaxTVar);
133 free(buf);
134 return res;
138 ////////////////////////////////////////////////////////////////////////////////
139 #include "vm_gamelabelsdef.c"
140 void initLabels (void) {
141 #include "vm_gamelabelsinit.c"
145 ////////////////////////////////////////////////////////////////////////////////
146 #ifndef AWISH_NO_SOUND
147 typedef struct SoundInfo {
148 struct SoundInfo *next;
149 int idx;
150 Mix_Chunk *data;
151 } SoundInfo;
153 static SoundInfo *sndlist = NULL;
156 static SoundInfo *findSound (int idx) {
157 for (SoundInfo *snd = sndlist; snd != NULL; snd = snd->next) if (snd->idx == idx) return snd;
158 return NULL;
162 int loadSound (int idx) {
163 SoundInfo *snd = findSound(idx);
165 if (snd == NULL) {
166 Mix_Chunk *data = loadSoundFile(&sndfile, idx);
168 if (data != NULL) {
169 snd = malloc(sizeof(SoundInfo));
170 if (snd != NULL) {
171 snd->next = sndlist;
172 snd->idx = idx;
173 snd->data = data;
174 sndlist = snd;
175 } else {
176 Mix_FreeChunk(data);
180 return (snd != NULL) ? 0 : -1;
184 int unloadSound (int idx) {
185 SoundInfo *snd, *p;
187 for (p = NULL, snd = sndlist; snd != NULL; p = snd, snd = snd->next) {
188 if (snd->idx == idx) {
189 Mix_FreeChunk(snd->data);
190 if (p != NULL) p->next = snd->next; else sndlist = snd->next;
191 free(snd);
192 return 0;
196 return -1;
200 int isSoundLoaded (int idx) {
201 return findSound(idx) ? 1 : 0;
205 int playSound (int idx, int chan) {
206 if (!SOUND_DISABLED) {
207 SoundInfo *snd = findSound(idx);
209 if (snd == 0) {
210 if (loadSound(idx) != 0) return -1;
211 snd = findSound(idx);
212 if (snd == NULL) return -1;
215 return Mix_PlayChannel(chan, snd->data, 0);
217 return -1;
221 int stopChannel (int chan) {
222 if (!SOUND_DISABLED) Mix_HaltChannel(chan);
223 return 0;
227 int isChannelPlaying (int chan) {
228 return Mix_Playing(chan);
232 void unloadAllSounds (void) {
233 Mix_HaltChannel(-1); // stop all sounds
234 while (sndlist != NULL) {
235 SoundInfo *c = sndlist;
237 sndlist = c->next;
238 Mix_FreeChunk(c->data);
239 free(c);
243 #else
245 int loadSound (int idx) {
246 return -1;
250 int unloadSound (int idx) {
251 return -1;
255 int isSoundLoaded (int idx) {
256 return 0;
260 int playSound (int idx, int chan) {
261 return -1;
265 int stopChannel (int chan) {
266 return 0;
270 int isChannelPlaying (int chan) {
271 return 0;
275 void unloadAllSounds (void) {
277 #endif
280 ////////////////////////////////////////////////////////////////////////////////
281 // return # of sprites loaded or <0 on error
282 int loadSpriteBankFromFile (SpriteBank *bank, const char *fname) {
283 Uint8 *buf;
284 int sz, pos;
286 if ((buf = loadDiskFileEx(fname, &sz)) == NULL) return -1;
287 if (sz < 3) { free(buf); return -1; }
288 pos = 0;
289 for (int f = bank->count-1; f >= 0; --f) {
290 SDL_FreeSurface(bank->spr[f][1]);
291 SDL_FreeSurface(bank->spr[f][0]);
293 bank->count = 0;
294 while (pos+4 <= sz) {
295 int h = ((Uint32)buf[pos+0])+256*((Uint32)buf[pos+1]);
296 int w = ((Uint32)buf[pos+2])+256*((Uint32)buf[pos+3]);
298 pos += 4;
299 if (h > 0 && w > 0) {
300 SDL_Surface *s0 = createSurface(w*2, h*2);
301 SDL_Surface *s1 = createSurface(w*2, h*2);
303 if (!s0 || !s1) { free(buf); return -1; }
305 for (int y = 0; y < h; ++y) {
306 for (int x = 0; x < w; ++x) {
307 if (pos < sz) {
308 putPixel2x(s0, x, y, buf[pos]);
309 putPixel2x(s1, w-x-1, y, buf[pos]);
310 ++pos;
314 bank->spr[bank->count][0] = s0;
315 bank->spr[bank->count][1] = s1;
316 ++(bank->count);
319 free(buf);
320 return bank->count;
324 ////////////////////////////////////////////////////////////////////////////////
325 typedef struct {
326 int x, y;
327 int bank;
328 int num;
329 int dir;
330 int inlevel;
331 } SpriteInfo;
334 typedef struct {
335 int count;
336 int size; // # of slots
337 SpriteInfo *list;
338 } SpriteLayer;
341 #define MAX_LAYER (63)
342 static SpriteLayer spLayers[MAX_LAYER+1];
343 static int spLayersInitialized = 0;
346 void clearSpriteLayers (void) {
347 if (!spLayersInitialized) {
348 for (int f = 0; f <= MAX_LAYER; ++f) {
349 spLayers[f].size = 0;
350 spLayers[f].list = NULL;
352 spLayersInitialized = 1;
354 for (int f = 0; f <= MAX_LAYER; ++f) spLayers[f].count = 0;
358 void addSpriteToLayer (int x, int y, int layer, int bank, int num, int dir, int inlevel) {
359 //fprintf(stderr, "*x=%d, y=%d, layer=%d, bank=%d, num=%d, dir=%d, inlevel=%d\n", x, y, layer, bank, num, dir, inlevel);
360 if (layer >= 0 && layer <= MAX_LAYER &&
361 bank >= 0 && bank <= 256 &&
362 num >= 0 && num < 256) {
364 if (spLayers[layer].count+1 >= spLayers[layer].size) {
365 int newsz = spLayers[layer].size+64;
366 SpriteInfo *n = realloc(spLayers[layer].list, newsz);
368 if (n == NULL) fatal("out of memory");
369 spLayers[layer].list = n;
370 spLayers[layer].size = newsz;
373 SpriteInfo *si = spLayers[layer].list+(spLayers[layer].count++);
375 si->x = x;
376 si->y = y;
377 si->bank = bank;
378 si->num = num;
379 si->dir = dir;
380 si->inlevel = inlevel;
385 void levelDrawSpriteLayers (SDL_Surface *frame, int visx, int visy, int visw, int vish) {
386 SDL_Rect rc;
388 rc.x = visx*2;
389 rc.y = visy*2;
390 rc.w = visw*2;
391 rc.h = vish*2;
392 SDL_SetClipRect(frame, &rc);
393 for (int f = MAX_LAYER; f >= 0; --f) {
394 SpriteInfo *list = spLayers[f].list;
396 if (list == NULL && spLayers[f].count != 0) {
397 fatal("WTF? f=%d; count=%d", f, spLayers[f].count);
399 for (int c = spLayers[f].count; c > 0; --c, ++list) {
400 if (list->inlevel &&
401 list->dir >= 0 && list->dir <= 1 &&
402 list->bank >= 0 && list->bank <= 256 &&
403 list->num >= 0 && list->num < banks[list->bank].count &&
404 banks[list->bank].spr[list->num][list->dir]) {
405 blitSurface2x(frame, visx+list->x, visy+list->y, banks[list->bank].spr[list->num][list->dir]);
410 SDL_SetClipRect(frame, NULL);
411 for (int f = MAX_LAYER; f >= 0; --f) {
412 SpriteInfo *list = spLayers[f].list;
414 if (list == NULL) continue;
415 for (int c = spLayers[f].count; c > 0; --c, ++list) {
416 //fprintf(stderr, ":x=%d, y=%d, layer=%d, bank=%d, num=%d, dir=%d, inlevel=%d\n", list->x, list->y, f, list->bank, list->num, list->dir, list->inlevel);
417 if (!list->inlevel &&
418 list->dir >= 0 && list->dir <= 1 &&
419 list->bank >= 0 && list->bank <= 256 &&
420 list->num >= 0 && list->num < banks[list->bank].count &&
421 banks[list->bank].spr[list->num][list->dir]) {
422 blitSurface2x(frame, list->x, list->y, banks[list->bank].spr[list->num][list->dir]);
429 ////////////////////////////////////////////////////////////////////////////////
430 typedef struct Poly {
431 struct Poly *next;
432 int ofsx;
433 int ofsy;
434 int scale;
435 int angle;
436 int color;
437 int alpha;
438 int size;
439 int used;
440 int *points;
441 } Poly;
444 static Poly *plist = NULL, *ptail = NULL;
447 void pmClear (void) {
448 while (plist != NULL) {
449 Poly *c = plist;
451 plist = c->next;
452 if (c->points != NULL) free(c->points);
453 free(c);
455 ptail = plist = NULL;
459 void pmStart (int ofsx, int ofsy, int scale, int angle) {
460 Poly *p = calloc(1, sizeof(Poly));
462 if (p == NULL) fatal("out of memory");
463 p->ofsx = ofsx;
464 p->ofsy = ofsy;
465 p->scale = scale;
466 p->angle = angle;
467 p->points = NULL;
468 p->used = p->size = 0;
469 p->alpha = 0;
470 p->next = NULL;
471 if (ptail != NULL) ptail->next = p; else plist = p;
472 ptail = p;
476 void pmAddPoint (int x, int y) {
477 if (ptail != NULL) {
478 if (ptail->used+2 > ptail->size) {
479 int newsz = ptail->size+128;
480 int *np = realloc(ptail->points, newsz*sizeof(int));
482 if (np == NULL) fatal("out of memory");
483 ptail->points = np;
484 ptail->size = newsz;
486 ptail->points[ptail->used++] = x;
487 ptail->points[ptail->used++] = y;
492 void pmDone (int color, int alpha) {
493 if (ptail != NULL && ptail->used > 0) {
494 if (color < 0) color = 0; else if (color > 255) color = 255;
495 if (alpha < 0) alpha = 0; else if (alpha > 255) alpha = 255;
496 ptail->color = color;
497 ptail->alpha = alpha;
502 void pmDraw (SDL_Surface *frame) {
503 for (Poly *p = plist; p != NULL; p = p->next) {
504 if (p->used > 0 && p->alpha > 0) {
505 polymodStart(p->ofsx, p->ofsy, p->scale, p->angle);
506 for (int f = 0; f < p->used; f += 2) polymodAddPoint(p->points[f], p->points[f+1]);
507 polymodEnd();
508 polymodFill(frame, p->color, p->alpha);
514 ////////////////////////////////////////////////////////////////////////////////
515 typedef struct Text {
516 struct Text *next;
517 char *str;
518 int len;
519 int x;
520 int y;
521 int scale;
522 int angle;
523 int color;
524 int alpha;
525 } Text;
528 static Text *tlist = NULL, *ttail = NULL;
531 void textClear (void) {
532 while (tlist != NULL) {
533 Text *c = tlist;
535 tlist = c->next;
536 if (c->str) free(c->str);
537 free(c);
539 ttail = NULL;
543 void textAdd (const char *str, int len, int x, int y, int scale, int angle, int color, int alpha) {
544 Text *p;
546 if (str == NULL) return;
547 if (len < 0) len = strlen(str);
548 if ((p = calloc(1, sizeof(Text))) == NULL) fatal("out of memory");
549 if ((p->str = calloc(len+1, 1)) == NULL) { free(p); fatal("out of memory"); }
550 if (color < 0) color = 0; else if (color > 255) color = 255;
551 if (alpha < 0) alpha = 0; else if (alpha > 255) alpha = 255;
552 p->x = x;
553 p->y = y;
554 p->scale = scale;
555 p->angle = angle;
556 p->color = color;
557 p->alpha = alpha;
558 if (len > 0) memcpy(p->str, str, len);
559 p->next = NULL;
560 if (ttail != NULL) ttail->next = p; else tlist = p;
561 ttail = p;
565 void textDraw (SDL_Surface *frame) {
566 for (Text *t = tlist; t != NULL; t = t->next) {
567 polymodStr(frame, t->str, t->x, t->y, t->scale, t->angle, t->color, t->alpha);