Mercurial > sdl-ios-xcode
annotate test/testpalette.c @ 1180:bdcb8bb4c831
From: Tyler Montbriand <tsm@accesscomm.ca>
To: sdl@libsdl.org
Date: Fri, 30 Sep 2005 02:24:50 -0600
Subject: [SDL] WinCE timers, continued
Here's a strange timer for Windows CE that doesn't ignore time across
suspends. It uses GetSystemTime to keep the time continuous, and GetTicks to
get finer-grained readings than 1 second. It detects the difference between
the GetTicks time and GetSystemTime time on power-on to keep the error within
one second max.
It's not a patch on the current win32 timer code -- took one look at that and
figured it had more than enough #ifdefs already. It's windows-ce specific.
Another thing I've noticed is that the Windows CE 4.0 and newer API has
functions warn processes about suspends. This is something SDL REALLY needs
for audio in particular, because turning it off while it's playing causes
anything that uses audio to hardlock the system on power-on. Unfortunately I
don't have 4.0 to play with. :(
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Tue, 22 Nov 2005 07:10:07 +0000 |
parents | be9c9c8f6d53 |
children | aff0170f9f1b |
rev | line source |
---|---|
0 | 1 /* |
2 * testpalette.c | |
3 * | |
4 * A simple test of runtime palette modification for animation | |
5 * (using the SDL_SetPalette() API). | |
6 */ | |
7 | |
8 #include <stdio.h> | |
9 #include <stdlib.h> | |
10 #include <string.h> | |
11 #include <math.h> | |
12 | |
13 /* This isn't in the Windows headers */ | |
14 #ifndef M_PI | |
15 #define M_PI 3.14159265358979323846 | |
16 #endif | |
17 | |
18 #include <SDL.h> | |
19 | |
20 /* screen size */ | |
21 #define SCRW 640 | |
22 #define SCRH 480 | |
23 | |
24 #define NBOATS 5 | |
25 #define SPEED 2 | |
26 | |
27 #ifndef MIN | |
28 #define MIN(a, b) ((a) < (b) ? (a) : (b)) | |
29 #endif | |
30 #ifndef MAX | |
31 #define MAX(a, b) ((a) > (b) ? (a) : (b)) | |
32 #endif | |
33 | |
34 /* | |
35 * wave colours: Made by taking a narrow cross-section of a wave picture | |
36 * in Gimp, saving in PPM ascii format and formatting with Emacs macros. | |
37 */ | |
38 static SDL_Color wavemap[] = { | |
39 {0,2,103}, {0,7,110}, {0,13,117}, {0,19,125}, | |
40 {0,25,133}, {0,31,141}, {0,37,150}, {0,43,158}, | |
41 {0,49,166}, {0,55,174}, {0,61,182}, {0,67,190}, | |
42 {0,73,198}, {0,79,206}, {0,86,214}, {0,96,220}, | |
43 {5,105,224}, {12,112,226}, {19,120,227}, {26,128,229}, | |
44 {33,135,230}, {40,143,232}, {47,150,234}, {54,158,236}, | |
45 {61,165,238}, {68,173,239}, {75,180,241}, {82,188,242}, | |
46 {89,195,244}, {96,203,246}, {103,210,248}, {112,218,250}, | |
47 {124,224,250}, {135,226,251}, {146,229,251}, {156,231,252}, | |
48 {167,233,252}, {178,236,252}, {189,238,252}, {200,240,252}, | |
49 {211,242,252}, {222,244,252}, {233,247,252}, {242,249,252}, | |
50 {237,250,252}, {209,251,252}, {174,251,252}, {138,252,252}, | |
51 {102,251,252}, {63,250,252}, {24,243,252}, {7,225,252}, | |
52 {4,203,252}, {3,181,252}, {2,158,252}, {1,136,251}, | |
53 {0,111,248}, {0,82,234}, {0,63,213}, {0,50,192}, | |
54 {0,39,172}, {0,28,152}, {0,17,132}, {0,7,114} | |
55 }; | |
56 | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
57 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
58 static void quit(int rc) |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
59 { |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
60 SDL_Quit(); |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
61 exit(rc); |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
62 } |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
63 |
0 | 64 static void sdlerr(char *when) |
65 { | |
66 fprintf(stderr, "SDL error: %s: %s\n", when, SDL_GetError()); | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
67 quit(1); |
0 | 68 } |
69 | |
70 /* create a background surface */ | |
71 static SDL_Surface *make_bg(SDL_Surface *screen, int startcol) | |
72 { | |
73 int i; | |
74 SDL_Surface *bg = SDL_CreateRGBSurface(SDL_SWSURFACE, screen->w, screen->h, | |
75 8, 0, 0, 0, 0); | |
76 if(!bg) | |
77 sdlerr("creating background surface"); | |
78 | |
79 /* set the palette to the logical screen palette so that blits | |
80 won't be translated */ | |
81 SDL_SetColors(bg, screen->format->palette->colors, 0, 256); | |
82 | |
83 /* Make a wavy background pattern using colours 0-63 */ | |
84 if(SDL_LockSurface(bg) < 0) | |
85 sdlerr("locking background"); | |
86 for(i = 0; i < SCRH; i++) { | |
87 Uint8 *p = (Uint8 *)bg->pixels + i * bg->pitch; | |
88 int j, d; | |
89 d = 0; | |
90 for(j = 0; j < SCRW; j++) { | |
91 int v = MAX(d, -2); | |
92 v = MIN(v, 2); | |
93 if(i > 0) | |
94 v += p[-bg->pitch] + 65 - startcol; | |
95 p[j] = startcol + (v & 63); | |
96 d += ((rand() >> 3) % 3) - 1; | |
97 } | |
98 } | |
99 SDL_UnlockSurface(bg); | |
100 return(bg); | |
101 } | |
102 | |
103 /* | |
104 * Return a surface flipped horisontally. Only works for 8bpp; | |
105 * extension to arbitrary bitness is left as an exercise for the reader. | |
106 */ | |
107 static SDL_Surface *hflip(SDL_Surface *s) | |
108 { | |
109 int i; | |
110 SDL_Surface *z = SDL_CreateRGBSurface(SDL_SWSURFACE, s->w, s->h, 8, | |
111 0, 0, 0, 0); | |
112 /* copy palette */ | |
113 SDL_SetColors(z, s->format->palette->colors, | |
114 0, s->format->palette->ncolors); | |
115 if(SDL_LockSurface(s) < 0 || SDL_LockSurface(z) < 0) | |
116 sdlerr("locking flip images"); | |
117 | |
118 for(i = 0; i < s->h; i++) { | |
119 int j; | |
120 Uint8 *from = (Uint8 *)s->pixels + i * s->pitch; | |
121 Uint8 *to = (Uint8 *)z->pixels + i * z->pitch + s->w - 1; | |
122 for(j = 0; j < s->w; j++) | |
123 to[-j] = from[j]; | |
124 } | |
125 | |
126 SDL_UnlockSurface(z); | |
127 SDL_UnlockSurface(s); | |
128 return z; | |
129 } | |
130 | |
131 int main(int argc, char **argv) | |
132 { | |
133 SDL_Color cmap[256]; | |
134 SDL_Surface *screen; | |
135 SDL_Surface *bg; | |
136 SDL_Surface *boat[2]; | |
137 unsigned vidflags = 0; | |
138 unsigned start; | |
139 int fade_max = 400; | |
140 int fade_level, fade_dir; | |
141 int boatcols, frames, i, red; | |
142 int boatx[NBOATS], boaty[NBOATS], boatdir[NBOATS]; | |
143 int gamma_fade = 0; | |
144 int gamma_ramp = 0; | |
145 | |
146 if(SDL_Init(SDL_INIT_VIDEO) < 0) | |
147 sdlerr("initialising SDL"); | |
148 | |
149 while(--argc) { | |
150 ++argv; | |
151 if(strcmp(*argv, "-hw") == 0) | |
152 vidflags |= SDL_HWSURFACE; | |
153 else if(strcmp(*argv, "-fullscreen") == 0) | |
154 vidflags |= SDL_FULLSCREEN; | |
155 else if(strcmp(*argv, "-nofade") == 0) | |
156 fade_max = 1; | |
157 else if(strcmp(*argv, "-gamma") == 0) | |
158 gamma_fade = 1; | |
159 else if(strcmp(*argv, "-gammaramp") == 0) | |
160 gamma_ramp = 1; | |
161 else { | |
162 fprintf(stderr, | |
163 "usage: testpalette " | |
164 " [-hw] [-fullscreen] [-nofade] [-gamma] [-gammaramp]\n"); | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
165 quit(1); |
0 | 166 } |
167 } | |
168 | |
169 /* Ask explicitly for 8bpp and a hardware palette */ | |
170 if(!(screen = SDL_SetVideoMode(SCRW, SCRH, 8, vidflags | SDL_HWPALETTE))) { | |
171 fprintf(stderr, "error setting %dx%d 8bpp indexed mode: %s\n", | |
172 SCRW, SCRH, SDL_GetError()); | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
173 quit(1); |
0 | 174 } |
175 | |
176 if(!(boat[0] = SDL_LoadBMP("sail.bmp"))) | |
177 sdlerr("loading sail.bmp"); | |
178 /* We've chosen magenta (#ff00ff) as colour key for the boat */ | |
179 SDL_SetColorKey(boat[0], SDL_SRCCOLORKEY | SDL_RLEACCEL, | |
180 SDL_MapRGB(boat[0]->format, 0xff, 0x00, 0xff)); | |
181 boatcols = boat[0]->format->palette->ncolors; | |
182 boat[1] = hflip(boat[0]); | |
183 SDL_SetColorKey(boat[1], SDL_SRCCOLORKEY | SDL_RLEACCEL, | |
184 SDL_MapRGB(boat[1]->format, 0xff, 0x00, 0xff)); | |
185 | |
186 /* | |
187 * First set the physical screen palette to black, so the user won't | |
188 * see our initial drawing on the screen. | |
189 */ | |
190 memset(cmap, 0, sizeof(cmap)); | |
191 SDL_SetPalette(screen, SDL_PHYSPAL, cmap, 0, 256); | |
192 | |
193 /* | |
194 * Proper palette management is important when playing games with the | |
195 * colormap. We have divided the palette as follows: | |
196 * | |
197 * index 0..(boatcols-1): used for the boat | |
198 * index boatcols..(boatcols+63): used for the waves | |
199 */ | |
200 SDL_SetPalette(screen, SDL_LOGPAL, | |
201 boat[0]->format->palette->colors, 0, boatcols); | |
202 SDL_SetPalette(screen, SDL_LOGPAL, wavemap, boatcols, 64); | |
203 | |
204 /* | |
205 * Now the logical screen palette is set, and will remain unchanged. | |
206 * The boats already have the same palette so fast blits can be used. | |
207 */ | |
208 memcpy(cmap, screen->format->palette->colors, 256 * sizeof(SDL_Color)); | |
209 | |
210 /* save the index of the red colour for later */ | |
211 red = SDL_MapRGB(screen->format, 0xff, 0x00, 0x00); | |
212 | |
213 bg = make_bg(screen, boatcols); /* make a nice wavy background surface */ | |
214 | |
215 /* initial screen contents */ | |
216 if(SDL_BlitSurface(bg, NULL, screen, NULL) < 0) | |
217 sdlerr("blitting background to screen"); | |
218 SDL_Flip(screen); /* actually put the background on screen */ | |
219 | |
220 /* determine initial boat placements */ | |
221 for(i = 0; i < NBOATS; i++) { | |
222 boatx[i] = (rand() % (SCRW + boat[0]->w)) - boat[0]->w; | |
223 boaty[i] = i * (SCRH - boat[0]->h) / (NBOATS - 1); | |
224 boatdir[i] = ((rand() >> 5) & 1) * 2 - 1; | |
225 } | |
226 | |
227 start = SDL_GetTicks(); | |
228 frames = 0; | |
229 fade_dir = 1; | |
230 fade_level = 0; | |
231 do { | |
232 SDL_Event e; | |
233 SDL_Rect updates[NBOATS]; | |
234 SDL_Rect r; | |
235 int redphase; | |
236 | |
237 /* A small event loop: just exit on any key or mouse button event */ | |
238 while(SDL_PollEvent(&e)) { | |
239 if(e.type == SDL_KEYDOWN || e.type == SDL_QUIT | |
240 || e.type == SDL_MOUSEBUTTONDOWN) { | |
241 if(fade_dir < 0) | |
242 fade_level = 0; | |
243 fade_dir = -1; | |
244 } | |
245 } | |
246 | |
247 /* move boats */ | |
248 for(i = 0; i < NBOATS; i++) { | |
249 int old_x = boatx[i]; | |
250 /* update boat position */ | |
251 boatx[i] += boatdir[i] * SPEED; | |
252 if(boatx[i] <= -boat[0]->w || boatx[i] >= SCRW) | |
253 boatdir[i] = -boatdir[i]; | |
254 | |
255 /* paint over the old boat position */ | |
256 r.x = old_x; | |
257 r.y = boaty[i]; | |
258 r.w = boat[0]->w; | |
259 r.h = boat[0]->h; | |
260 if(SDL_BlitSurface(bg, &r, screen, &r) < 0) | |
261 sdlerr("blitting background"); | |
262 | |
263 /* construct update rectangle (bounding box of old and new pos) */ | |
264 updates[i].x = MIN(old_x, boatx[i]); | |
265 updates[i].y = boaty[i]; | |
266 updates[i].w = boat[0]->w + SPEED; | |
267 updates[i].h = boat[0]->h; | |
268 /* clip update rectangle to screen */ | |
269 if(updates[i].x < 0) { | |
270 updates[i].w += updates[i].x; | |
271 updates[i].x = 0; | |
272 } | |
273 if(updates[i].x + updates[i].w > SCRW) | |
274 updates[i].w = SCRW - updates[i].x; | |
275 } | |
276 | |
277 for(i = 0; i < NBOATS; i++) { | |
278 /* paint boat on new position */ | |
279 r.x = boatx[i]; | |
280 r.y = boaty[i]; | |
281 if(SDL_BlitSurface(boat[(boatdir[i] + 1) / 2], NULL, | |
282 screen, &r) < 0) | |
283 sdlerr("blitting boat"); | |
284 } | |
285 | |
286 /* cycle wave palette */ | |
287 for(i = 0; i < 64; i++) | |
288 cmap[boatcols + ((i + frames) & 63)] = wavemap[i]; | |
289 | |
290 if(fade_dir) { | |
291 /* Fade the entire palette in/out */ | |
292 fade_level += fade_dir; | |
293 | |
294 if(gamma_fade) { | |
295 /* Fade linearly in gamma level (lousy) */ | |
296 float level = (float)fade_level / fade_max; | |
297 if(SDL_SetGamma(level, level, level) < 0) | |
298 sdlerr("setting gamma"); | |
299 | |
300 } else if(gamma_ramp) { | |
301 /* Fade using gamma ramp (better) */ | |
302 Uint16 ramp[256]; | |
303 for(i = 0; i < 256; i++) | |
304 ramp[i] = (i * fade_level / fade_max) << 8; | |
305 if(SDL_SetGammaRamp(ramp, ramp, ramp) < 0) | |
306 sdlerr("setting gamma ramp"); | |
307 | |
308 } else { | |
309 /* Fade using direct palette manipulation (best) */ | |
310 memcpy(cmap, screen->format->palette->colors, | |
311 boatcols * sizeof(SDL_Color)); | |
312 for(i = 0; i < boatcols + 64; i++) { | |
313 cmap[i].r = cmap[i].r * fade_level / fade_max; | |
314 cmap[i].g = cmap[i].g * fade_level / fade_max; | |
315 cmap[i].b = cmap[i].b * fade_level / fade_max; | |
316 } | |
317 } | |
318 if(fade_level == fade_max) | |
319 fade_dir = 0; | |
320 } | |
321 | |
322 /* pulse the red colour (done after the fade, for a night effect) */ | |
323 redphase = frames % 64; | |
324 cmap[red].r = (int)(255 * sin(redphase * M_PI / 63)); | |
325 | |
326 SDL_SetPalette(screen, SDL_PHYSPAL, cmap, 0, boatcols + 64); | |
327 | |
328 /* update changed areas of the screen */ | |
329 SDL_UpdateRects(screen, NBOATS, updates); | |
330 frames++; | |
331 } while(fade_level > 0); | |
332 | |
333 printf("%d frames, %.2f fps\n", | |
334 frames, 1000.0 * frames / (SDL_GetTicks() - start)); | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
335 |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
336 SDL_Quit(); |
0 | 337 return 0; |
338 } | |
339 |