Add SDL2_mixer support.
[runemen.git] / src / sdl2-x.c
blob52213357ef0c85b137a6646f6b80816ff200035a
1 /* Definitive version of sdl-x. Please symlink here OR DIE */
2 #include <SDL.h>
4 #ifdef HAVE_SCALE2X
5 #include "scale2x.h"
6 #endif
8 #ifdef HAVE_SDLMIXER
9 #include <SDL/SDL_mixer.h>
10 Mix_Chunk *sounds[255];
11 int loaded_wavs = 0;
12 //int audio_open = 0;
13 #endif
15 #define SDL_CloneSurfaceX(SURFACE, SIZE) SDL_CreateRGBSurface(SURFACE->flags, SURFACE->w * SIZE, SURFACE->h * SIZE, SURFACE->format->BitsPerPixel, \
16 SURFACE->format->Rmask, SURFACE->format->Gmask, SURFACE->format->Bmask, SURFACE->format->Amask)
17 #define SDL_CloneSurfaceR(SURFACE) SDL_CreateRGBSurface(SURFACE->flags, SURFACE->h, SURFACE->w, SURFACE->format->BitsPerPixel, \
18 SURFACE->format->Rmask, SURFACE->format->Gmask, SURFACE->format->Bmask, SURFACE->format->Amask)
20 Uint32 getpixel(SDL_Surface *surface, int x, int y)
22 int bpp = surface->format->BytesPerPixel;
23 /* Here p is the address to the pixel we want to retrieve */
24 Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
26 switch(bpp) {
27 case 1:
28 return *p;
29 break;
31 case 2:
32 return *(Uint16 *)p;
33 break;
35 case 3:
36 if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
37 return p[0] << 16 | p[1] << 8 | p[2];
38 else
39 return p[0] | p[1] << 8 | p[2] << 16;
40 break;
42 case 4:
43 return *(Uint32 *)p;
44 break;
46 default:
47 return 0; /* shouldn't happen, but avoids warnings */
52 * Rotate surface 90 degrees (returns NEW surface)
54 SDL_Surface* rot90_surface(SDL_Surface* surface)
56 SDL_Surface* new_surface = NULL;
57 Uint8 bpp = surface->format->BytesPerPixel;
58 Uint8 *source, *dest, p;
59 Uint16 x, y;
61 new_surface = SDL_CloneSurfaceR(surface);
62 // SDL_SetPalette(new_surface, SDL_LOGPAL | SDL_PHYSPAL, surface->format->palette->colors, 0, surface->format->palette->ncolors);
64 if (new_surface == NULL) {
65 fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
66 return NULL;
69 source = (Uint8*)(surface->pixels);
70 dest = (Uint8*)(new_surface->pixels);
72 for(y = 0; y < surface->h; y++)
73 for(x = 0; x < surface->w; x++)
75 int dx = new_surface->h - y - 1;
76 int dy = x;
77 for (p = 0; p < bpp; p++)
79 dest[ dy * (new_surface->w * bpp) + (dx * bpp) + p ] =
80 source[ y * (surface->w * bpp) + (x * bpp) + p ];
83 return new_surface;
87 * Flip surface horizontally (returns NEW surface)
89 SDL_Surface* flip_surface(SDL_Surface* surface)
91 SDL_Surface* new_surface = NULL;
92 Uint8 bpp = surface->format->BytesPerPixel;
93 Uint8 *source, *dest, p;
94 Uint16 x, y;
96 new_surface = SDL_CloneSurfaceX(surface, 1);
97 // SDL_SetPalette(new_surface, SDL_LOGPAL | SDL_PHYSPAL, surface->format->palette->colors, 0, surface->format->palette->ncolors);
99 if (new_surface == NULL) {
100 fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
101 return NULL;
104 source = (Uint8*)(surface->pixels);
105 dest = (Uint8*)(new_surface->pixels);
107 for(y = 0; y < new_surface->h; y++)
108 for(x = 0; x < new_surface->w; x++)
109 for (p = 0; p < bpp; p++)
111 dest[ y * (new_surface->w * bpp) + (x * bpp) + p ] =
112 source[ (y + 1) * (new_surface->w * bpp) - ((x+1) * bpp) + p ];
115 return new_surface;
119 * Double surface in size (dumb)
121 void sizex(SDL_Surface *surface, SDL_Surface *new_surface, Uint8 size)
123 Uint32 x, y;
124 Uint8 bpp = surface->format->BytesPerPixel, cx, cy, p;
125 Uint8 *source, *dest;
127 source = (Uint8*)(surface->pixels);
128 dest = (Uint8*)(new_surface->pixels);
130 for(y = 0; y < surface->h; y++)
131 for(x = 0; x < surface->w; x++)
132 for (p = 0; p < bpp; p++)
133 for (cy = 0; cy < size; cy++)
134 for (cx = 0; cx < size; cx++)
136 dest[ (y * size + cy) * (new_surface->w * bpp) + ( (x * size + cx) * bpp) + p ] =
137 source[ y * (surface->w * bpp) + (x * bpp) + p ];
141 SDL_Surface* sizex_surface(SDL_Surface* surface, Uint8 size)
143 SDL_Surface* new_surface = NULL;
145 new_surface = SDL_CloneSurfaceX(surface, size);
146 // SDL_SetPalette(new_surface, SDL_LOGPAL | SDL_PHYSPAL, surface->format->palette->colors, 0, surface->format->palette->ncolors);
148 sizex(surface, new_surface, size);
150 return new_surface;
154 * Prepare matching surface and perform AdvancedMAME's scale2x implementation
156 #ifdef HAVE_SCALE2X
157 SDL_Surface* scale2x_surface(SDL_Surface* surface)
159 SDL_Surface* new_surface = NULL;
161 new_surface = SDL_CloneSurfaceX(surface, 2);
162 SDL_SetPalette(new_surface, SDL_LOGPAL | SDL_PHYSPAL, surface->format->palette->colors, 0, surface->format->palette->ncolors);
164 scale2x(surface, new_surface);
166 return new_surface;
168 #endif
172 #ifndef HAVE_SDLMIXER
173 void init_sound() { }
174 int load_sound(const char * buf) { return -1; }
175 void play_sound(int id) { }
176 void close_sound() { }
177 #else
179 * Init sound
181 void init_sound() {
182 /* Desired audio parameters */
183 int audio_rate;
184 Uint16 audio_format;
185 int audio_channels;
186 int loops = 2;
187 int i;
189 /* Initialize variables */
190 audio_rate = 44100;//MIX_DEFAULT_FREQUENCY;
191 audio_format = MIX_DEFAULT_FORMAT;
192 audio_channels = 2;
194 /* Open the audio device */
195 if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, 4096) < 0) {
196 fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
197 } else {
198 Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels);
199 printf("Opened audio at %d Hz %d bit %s", audio_rate,
200 (audio_format&0xFF),
201 (audio_channels > 2) ? "surround" :
202 (audio_channels > 1) ? "stereo" : "mono");
203 if ( loops ) {
204 printf(" (looping)\n");
205 } else {
206 putchar('\n');
209 //audio_open = 1;
211 // allocate 16 mixing channels
212 //Mix_AllocateChannels(16);
213 //Mix_ChannelFinished(channel_complete_callback);
217 * Load a sound
219 void assign_sound(int id, Mix_Chunk *wave) {
220 sounds[id] = wave;
222 int load_sound(const char * buf) {
223 /* Load the requested wave file */
224 Mix_Chunk *wave = Mix_LoadWAV(buf);
225 if ( wave == NULL ) {
226 fprintf(stderr, "Couldn't load %s: %s\n", buf, SDL_GetError());
227 return -1;
229 sounds[loaded_wavs++] = wave;
230 printf("Sound %d = %s\n", loaded_wavs-1, buf);
231 return (loaded_wavs-1);
235 * Make a sound
237 void play_sound(int id) {
238 Mix_Chunk *wav = sounds[id];
240 /* Start playing */
241 Mix_PlayChannel(-1, wav, 0);
245 * Close sound
247 void close_sound() {
250 #endif
253 ** Lazy Helpers
255 SDL_Rect* lazy_rect(Uint32 x, Uint32 y, Uint32 w, Uint32 h) {
256 static SDL_Rect rects[16];
257 static Uint8 index = 0;
259 if (index++ > 16) index = 0;
261 rects[index].x = x;
262 rects[index].y = y;
263 rects[index].w = w;
264 rects[index].h = h;
266 return &rects[index];
268 Uint32 lazy_timer(Uint8 id) {
269 static Uint32 times[16] = /* Make sure 16 zeros are here :( */
270 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
271 Uint32 passed, microsec;
273 microsec = SDL_GetTicks();
274 passed = (!times[id] ? 0 : microsec - times[id]);
275 times[id] = microsec;
277 return passed;
279 Uint32 lazy_delay(Uint8 id, Uint32 test) {
280 static Uint32 times[16] = /* Make sure 16 zeros are here :( */
281 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
282 Uint32 passed, microsec;
284 microsec = SDL_GetTicks();
285 if (!times[id]) times[id] = microsec;
286 passed = microsec - times[id];
287 if (passed >= test) {
288 times[id] = microsec;
289 passed = 0;
291 return passed;
295 ** HSV tools
297 /* Convert RGB to HSV (RGBSV are in 0-255 range, H might be not... :( ) */
298 void setHSV(Uint8 r, Uint8 g, Uint8 b, Uint8 *h, Uint8 *s, Uint8 *v)
300 // RGB are from 0..1, H is from 0..360, SV from 0..1
302 Uint8 maxC = b; if (maxC < g) maxC = g; if (maxC < r) maxC = r;
303 Uint8 minC = b; if (minC > g) minC = g; if (minC > r) minC = r;
305 double R = (double)r / 255;
306 double G = (double)g / 255;
307 double B = (double)b / 255;
309 double M = (double)maxC / 255;
310 double m = (double)minC / 255;
311 double C = M - m;
313 double V = M;
314 double S = 0;
315 double H = 0;
317 if (C == 0)
319 H = 0;
320 S = 0;
322 else
324 double dR = 60 * (M - R) / C + 180;
325 double dG = 60 * (M - G) / C + 180;
326 double dB = 60 * (M - B) / C + 180;
327 if (r == maxC) H = dB - dG;
328 else if (g == maxC) H = 120 + dR - dB;
329 else H = 240 + dG - dR;
330 if (H < 0) H += 360;
331 if (H >= 360) H -= 360;
332 S = C / M;
334 *h = H;
335 *s = S * 255;
336 *v = V * 255;
338 /* Convert HSV to RGB */
339 void setRGB(Uint8 h, Uint8 s, Uint8 v, Uint8 *r, Uint8 *g, Uint8 *b)
341 double p, q, t;
342 Uint8 f;
344 if (s == 0)
346 *r = *g = *b = v;
347 return;
349 f = ((h % 60) * 255) / 60;
350 h /= 60;
351 p = (v * (256 - s)) / 256;
352 q = (v * (256 - (s * f) / 256)) / 256;
353 t = (v * (256 - (s * (256 - f)) / 256)) / 256;
354 switch( h )
356 case 0: *r = v; *g = t; *b = p; break;
357 case 1: *r = q; *g = v; *b = p; break;
358 case 2: *r = p; *g = v; *b = t; break;
359 case 3: *r = p; *g = q; *b = v; break;
360 case 4: *r = t; *g = p; *b = v; break;
361 default: *r = v; *g = p; *b = q; break;
365 typedef struct SDL_Shade {
366 Uint8 h;
367 Uint8 s;
368 Uint8 v;
369 Uint8 a;
370 } SDL_Shade;
372 void SDL_ComputeGradient(SDL_Color *colors, int n, SDL_Color *start, SDL_Color *stop) {
374 SDL_Shade _start;
375 SDL_Shade _stop;
377 setHSV(start->r, start->g, start->b, &_start.h, &_start.s, &_start.v);
378 setHSV(stop->r, stop->g, stop->b, &_stop.h, &_stop.s, &_stop.v);
380 int i = 0;
381 double f = 0;
382 double step = 1.0f / n;
383 //printf("STEP: %f\n", step);
384 for (i = 0; i < n; i++) {
385 int r, g, b;
386 //linear: pu = p0 + u(p1 - p0)
388 double H = (double)_start.h + f * (_stop.h - _start.h);
389 double S = (double)_start.s + f * (_stop.s - _start.s);
390 double V = (double)_start.v + f * (_stop.v - _start.v);
391 setRGB((int)H, (int)S, (int)V , &r, &g, &b);
394 double R = (double)start->r + f * (stop->r - start->r);
395 double G = (double)start->g + f * (stop->g - start->g);
396 double B = (double)start->b + f * (stop->b - start->b);
397 r = (int)R; g = (int)G; b = (int)B;
399 //printf("COLOR %d - %02x %02x %02x \n", i, r,g,b);
400 colors->r = r;
401 colors->g = g;
402 colors->b = b;
403 colors->a = 0xff;
404 colors++;
405 f += step;