19682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
29682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * testpalette.c
39682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *
49682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * A simple test of runtime palette modification for animation
59682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * (using the SDL_SetPalette() API).
69682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
79682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
89682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <stdio.h>
99682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <stdlib.h>
109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <string.h>
119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <math.h>
129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* This isn't in the Windows headers */
149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef M_PI
159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define M_PI	3.14159265358979323846
169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL.h"
199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* screen size */
219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define SCRW 640
229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define SCRH 480
239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define NBOATS 5
259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define SPEED 2
269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef MIN
289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MIN(a, b) ((a) < (b) ? (a) : (b))
299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef MAX
319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MAX(a, b) ((a) > (b) ? (a) : (b))
329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * wave colours: Made by taking a narrow cross-section of a wave picture
369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * in Gimp, saving in PPM ascii format and formatting with Emacs macros.
379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_Color wavemap[] = {
399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {0,2,103}, {0,7,110}, {0,13,117}, {0,19,125},
409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {0,25,133}, {0,31,141}, {0,37,150}, {0,43,158},
419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {0,49,166}, {0,55,174}, {0,61,182}, {0,67,190},
429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {0,73,198}, {0,79,206}, {0,86,214}, {0,96,220},
439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {5,105,224}, {12,112,226}, {19,120,227}, {26,128,229},
449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {33,135,230}, {40,143,232}, {47,150,234}, {54,158,236},
459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {61,165,238}, {68,173,239}, {75,180,241}, {82,188,242},
469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {89,195,244}, {96,203,246}, {103,210,248}, {112,218,250},
479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {124,224,250}, {135,226,251}, {146,229,251}, {156,231,252},
489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {167,233,252}, {178,236,252}, {189,238,252}, {200,240,252},
499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {211,242,252}, {222,244,252}, {233,247,252}, {242,249,252},
509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {237,250,252}, {209,251,252}, {174,251,252}, {138,252,252},
519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {102,251,252}, {63,250,252}, {24,243,252}, {7,225,252},
529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {4,203,252}, {3,181,252}, {2,158,252}, {1,136,251},
539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {0,111,248}, {0,82,234}, {0,63,213}, {0,50,192},
549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {0,39,172}, {0,28,152}, {0,17,132}, {0,7,114}
559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall};
569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void quit(int rc)
599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_Quit();
619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	exit(rc);
629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void sdlerr(char *when)
659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    fprintf(stderr, "SDL error: %s: %s\n", when, SDL_GetError());
679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    quit(1);
689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* create a background surface */
719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_Surface *make_bg(SDL_Surface *screen, int startcol)
729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int i;
749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_Surface *bg = SDL_CreateRGBSurface(SDL_SWSURFACE, screen->w, screen->h,
759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					   8, 0, 0, 0, 0);
769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if(!bg)
779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	sdlerr("creating background surface");
789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* set the palette to the logical screen palette so that blits
809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       won't be translated */
819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_SetColors(bg, screen->format->palette->colors, 0, 256);
829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Make a wavy background pattern using colours 0-63 */
849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if(SDL_LockSurface(bg) < 0)
859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	sdlerr("locking background");
869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for(i = 0; i < SCRH; i++) {
879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Uint8 *p = (Uint8 *)bg->pixels + i * bg->pitch;
889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int j, d;
899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	d = 0;
909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	for(j = 0; j < SCRW; j++) {
919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    int v = MAX(d, -2);
929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    v = MIN(v, 2);
939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    if(i > 0)
949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		v += p[-bg->pitch] + 65 - startcol;
959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    p[j] = startcol + (v & 63);
969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    d += ((rand() >> 3) % 3) - 1;
979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_UnlockSurface(bg);
1009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return(bg);
1019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
1029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
1049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Return a surface flipped horisontally. Only works for 8bpp;
1059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * extension to arbitrary bitness is left as an exercise for the reader.
1069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
1079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_Surface *hflip(SDL_Surface *s)
1089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
1099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int i;
1109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_Surface *z = SDL_CreateRGBSurface(SDL_SWSURFACE, s->w, s->h, 8,
1119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					  0, 0, 0, 0);
1129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* copy palette */
1139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_SetColors(z, s->format->palette->colors,
1149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		  0, s->format->palette->ncolors);
1159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if(SDL_LockSurface(s) < 0 || SDL_LockSurface(z) < 0)
1169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	sdlerr("locking flip images");
1179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for(i = 0; i < s->h; i++) {
1199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int j;
1209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Uint8 *from = (Uint8 *)s->pixels + i * s->pitch;
1219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Uint8 *to = (Uint8 *)z->pixels + i * z->pitch + s->w - 1;
1229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	for(j = 0; j < s->w; j++)
1239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    to[-j] = from[j];
1249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
1259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_UnlockSurface(z);
1279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_UnlockSurface(s);
1289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return z;
1299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
1309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint main(int argc, char **argv)
1329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
1339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_Color cmap[256];
1349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_Surface *screen;
1359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_Surface *bg;
1369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_Surface *boat[2];
1379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    unsigned vidflags = 0;
1389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    unsigned start;
1399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int fade_max = 400;
1409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int fade_level, fade_dir;
1419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int boatcols, frames, i, red;
1429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int boatx[NBOATS], boaty[NBOATS], boatdir[NBOATS];
1439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int gamma_fade = 0;
1449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int gamma_ramp = 0;
1459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if(SDL_Init(SDL_INIT_VIDEO) < 0)
1479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	sdlerr("initialising SDL");
1489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    while(--argc) {
1509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	++argv;
1519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(strcmp(*argv, "-hw") == 0)
1529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    vidflags |= SDL_HWSURFACE;
1539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	else if(strcmp(*argv, "-fullscreen") == 0)
1549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    vidflags |= SDL_FULLSCREEN;
1559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	else if(strcmp(*argv, "-nofade") == 0)
1569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    fade_max = 1;
1579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	else if(strcmp(*argv, "-gamma") == 0)
1589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    gamma_fade = 1;
1599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	else if(strcmp(*argv, "-gammaramp") == 0)
1609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    gamma_ramp = 1;
1619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	else {
1629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    fprintf(stderr,
1639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		    "usage: testpalette "
1649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		    " [-hw] [-fullscreen] [-nofade] [-gamma] [-gammaramp]\n");
1659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    quit(1);
1669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
1679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
1689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Ask explicitly for 8bpp and a hardware palette */
1709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if((screen = SDL_SetVideoMode(SCRW, SCRH, 8, vidflags | SDL_HWPALETTE)) == NULL) {
1719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	fprintf(stderr, "error setting %dx%d 8bpp indexed mode: %s\n",
1729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SCRW, SCRH, SDL_GetError());
1739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	quit(1);
1749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
1759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (vidflags & SDL_FULLSCREEN) SDL_ShowCursor (SDL_FALSE);
1779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if((boat[0] = SDL_LoadBMP("sail.bmp")) == NULL)
1799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	sdlerr("loading sail.bmp");
1809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* We've chosen magenta (#ff00ff) as colour key for the boat */
1819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_SetColorKey(boat[0], SDL_SRCCOLORKEY | SDL_RLEACCEL,
1829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		    SDL_MapRGB(boat[0]->format, 0xff, 0x00, 0xff));
1839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    boatcols = boat[0]->format->palette->ncolors;
1849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    boat[1] = hflip(boat[0]);
1859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_SetColorKey(boat[1], SDL_SRCCOLORKEY | SDL_RLEACCEL,
1869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		    SDL_MapRGB(boat[1]->format, 0xff, 0x00, 0xff));
1879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /*
1899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * First set the physical screen palette to black, so the user won't
1909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * see our initial drawing on the screen.
1919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     */
1929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    memset(cmap, 0, sizeof(cmap));
1939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_SetPalette(screen, SDL_PHYSPAL, cmap, 0, 256);
1949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /*
1969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * Proper palette management is important when playing games with the
1979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * colormap. We have divided the palette as follows:
1989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     *
1999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * index 0..(boatcols-1):		used for the boat
2009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * index boatcols..(boatcols+63):	used for the waves
2019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     */
2029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_SetPalette(screen, SDL_LOGPAL,
2039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		   boat[0]->format->palette->colors, 0, boatcols);
2049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_SetPalette(screen, SDL_LOGPAL, wavemap, boatcols, 64);
2059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /*
2079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * Now the logical screen palette is set, and will remain unchanged.
2089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * The boats already have the same palette so fast blits can be used.
2099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     */
2109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    memcpy(cmap, screen->format->palette->colors, 256 * sizeof(SDL_Color));
2119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* save the index of the red colour for later */
2139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    red = SDL_MapRGB(screen->format, 0xff, 0x00, 0x00);
2149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    bg = make_bg(screen, boatcols); /* make a nice wavy background surface */
2169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* initial screen contents */
2189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if(SDL_BlitSurface(bg, NULL, screen, NULL) < 0)
2199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	sdlerr("blitting background to screen");
2209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_Flip(screen);		/* actually put the background on screen */
2219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* determine initial boat placements */
2239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for(i = 0; i < NBOATS; i++) {
2249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	boatx[i] = (rand() % (SCRW + boat[0]->w)) - boat[0]->w;
2259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	boaty[i] = i * (SCRH - boat[0]->h) / (NBOATS - 1);
2269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	boatdir[i] = ((rand() >> 5) & 1) * 2 - 1;
2279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
2289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    start = SDL_GetTicks();
2309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    frames = 0;
2319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    fade_dir = 1;
2329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    fade_level = 0;
2339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    do {
2349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_Event e;
2359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_Rect updates[NBOATS];
2369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_Rect r;
2379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int redphase;
2389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* A small event loop: just exit on any key or mouse button event */
2409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	while(SDL_PollEvent(&e)) {
2419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    if(e.type == SDL_KEYDOWN || e.type == SDL_QUIT
2429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	       || e.type == SDL_MOUSEBUTTONDOWN) {
2439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if(fade_dir < 0)
2449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		    fade_level = 0;
2459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		fade_dir = -1;
2469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    }
2479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
2489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* move boats */
2509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	for(i = 0; i < NBOATS; i++) {
2519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    int old_x = boatx[i];
2529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    /* update boat position */
2539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    boatx[i] += boatdir[i] * SPEED;
2549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    if(boatx[i] <= -boat[0]->w || boatx[i] >= SCRW)
2559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		boatdir[i] = -boatdir[i];
2569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    /* paint over the old boat position */
2589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    r.x = old_x;
2599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    r.y = boaty[i];
2609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    r.w = boat[0]->w;
2619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    r.h = boat[0]->h;
2629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    if(SDL_BlitSurface(bg, &r, screen, &r) < 0)
2639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		sdlerr("blitting background");
2649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    /* construct update rectangle (bounding box of old and new pos) */
2669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    updates[i].x = MIN(old_x, boatx[i]);
2679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    updates[i].y = boaty[i];
2689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    updates[i].w = boat[0]->w + SPEED;
2699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    updates[i].h = boat[0]->h;
2709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    /* clip update rectangle to screen */
2719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    if(updates[i].x < 0) {
2729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		updates[i].w += updates[i].x;
2739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		updates[i].x = 0;
2749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    }
2759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    if(updates[i].x + updates[i].w > SCRW)
2769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		updates[i].w = SCRW - updates[i].x;
2779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
2789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	for(i = 0; i < NBOATS; i++) {
2809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    /* paint boat on new position */
2819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    r.x = boatx[i];
2829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    r.y = boaty[i];
2839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    if(SDL_BlitSurface(boat[(boatdir[i] + 1) / 2], NULL,
2849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			       screen, &r) < 0)
2859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		sdlerr("blitting boat");
2869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
2879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* cycle wave palette */
2899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	for(i = 0; i < 64; i++)
2909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    cmap[boatcols + ((i + frames) & 63)] = wavemap[i];
2919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(fade_dir) {
2939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    /* Fade the entire palette in/out */
2949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    fade_level += fade_dir;
2959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    if(gamma_fade) {
2979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Fade linearly in gamma level (lousy) */
2989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		float level = (float)fade_level / fade_max;
2999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if(SDL_SetGamma(level, level, level) < 0)
3009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		    sdlerr("setting gamma");
3019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    } else if(gamma_ramp) {
3039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Fade using gamma ramp (better) */
3049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		Uint16 ramp[256];
3059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		for(i = 0; i < 256; i++)
3069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		    ramp[i] = (i * fade_level / fade_max) << 8;
3079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if(SDL_SetGammaRamp(ramp, ramp, ramp) < 0)
3089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		    sdlerr("setting gamma ramp");
3099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    } else {
3119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Fade using direct palette manipulation (best) */
3129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		memcpy(cmap, screen->format->palette->colors,
3139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		       boatcols * sizeof(SDL_Color));
3149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		for(i = 0; i < boatcols + 64; i++) {
3159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		    cmap[i].r = cmap[i].r * fade_level / fade_max;
3169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		    cmap[i].g = cmap[i].g * fade_level / fade_max;
3179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		    cmap[i].b = cmap[i].b * fade_level / fade_max;
3189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
3199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    }
3209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    if(fade_level == fade_max)
3219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		fade_dir = 0;
3229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
3239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* pulse the red colour (done after the fade, for a night effect) */
3259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	redphase = frames % 64;
3269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	cmap[red].r = (int)(255 * sin(redphase * M_PI / 63));
3279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_SetPalette(screen, SDL_PHYSPAL, cmap, 0, boatcols + 64);
3299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* update changed areas of the screen */
3319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_UpdateRects(screen, NBOATS, updates);
3329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	frames++;
3339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    } while(fade_level > 0);
3349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    printf("%d frames, %.2f fps\n",
3369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	   frames, 1000.0 * frames / (SDL_GetTicks() - start));
3379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (vidflags & SDL_FULLSCREEN) SDL_ShowCursor (SDL_TRUE);
3399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_Quit();
3409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
3419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
3429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
343