~ubuntu-branches/ubuntu/maverick/crossfire-client/maverick

« back to all changes in this revision

Viewing changes to gtk-v2/src/sdl.c

  • Committer: Bazaar Package Importer
  • Author(s): Kari Pahula
  • Date: 2005-08-20 23:46:35 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20050820234635-m3nwl2a0190jc15f
Tags: 1.8.0-1
* New upstream release (closes: #298438)
* New maintainer
* Set datadir to /usr/share/games and sounddir to
  /usr/share/games/crossfire/sounds.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
char *rcsid_gtk_sdl_c =
 
2
    "$Id: sdl.c,v 1.4 2005/07/16 17:23:57 akirschbaum Exp $";
 
3
 
 
4
/*
 
5
    Crossfire client, a client program for the crossfire program.
 
6
 
 
7
    Copyright (C) 2005 Mark Wedel & Crossfire Development Team
 
8
 
 
9
    This program is free software; you can redistribute it and/or modify
 
10
    it under the terms of the GNU General Public License as published by
 
11
    the Free Software Foundation; either version 2 of the License, or
 
12
    (at your option) any later version.
 
13
 
 
14
    This program is distributed in the hope that it will be useful,
 
15
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
    GNU General Public License for more details.
 
18
 
 
19
    You should have received a copy of the GNU General Public License
 
20
    along with this program; if not, write to the Free Software
 
21
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
22
 
 
23
    The author can be reached via e-mail to crossfire@metalforge.org
 
24
*/
 
25
 
 
26
#include "config.h"
 
27
 
 
28
#ifdef HAVE_SDL
 
29
 
 
30
#include <client-types.h>
 
31
#include <SDL.h>
 
32
#include <SDL_image.h>
 
33
 
 
34
/* Pick up the gtk headers we need */
 
35
#include <gtk/gtk.h>
 
36
#include <gdk/gdkx.h>
 
37
#include <gdk/gdkkeysyms.h>
 
38
 
 
39
#include "main.h"
 
40
#include "image.h"
 
41
#include <client.h>
 
42
#include "gtk2proto.h"
 
43
 
 
44
/* Actual SDL surface the game view is painted on */
 
45
SDL_Surface* mapsurface;
 
46
static SDL_Surface* lightmap;
 
47
static SDL_Surface* fogmap;
 
48
static char *redrawbitmap;
 
49
 
 
50
extern int time_map_redraw;
 
51
extern uint8 map_did_scroll, map_updated;
 
52
 
 
53
 
 
54
/* Move some of the SDL code to this file here.  This makes it easier to share
 
55
 * between the gnome and gtk client.  It also reduces the length of both the gx11.c
 
56
 * and gnome.c file.  It also is more readable, as not as many #ifdef SDL.. #endif
 
57
 * constructs are needed.
 
58
 * Note that there may still be some SDL code in gx11.c - some areas are embedded
 
59
 * so much that it is not easy to remove.
 
60
 */
 
61
 
 
62
/* these should generally be included by the file including this file. */
 
63
#include <SDL.h>
 
64
#include <SDL_image.h>
 
65
 
 
66
 
 
67
static void do_SDL_error( char* SDL_function, char* file, int line)
 
68
{
 
69
  LOG(LOG_CRITICAL,SDL_function,"SDL error in file %s line %d\n%s",
 
70
           file, line, SDL_GetError());
 
71
  SDL_Quit();
 
72
  exit( 1);
 
73
}
 
74
 
 
75
/*
 
76
 * Set the pixel at (x, y) to the given value
 
77
 * NOTE: The surface must be locked before calling this!
 
78
 * This function is directly grabbed from the SDL docs.
 
79
 * Note this is not currently used, but is useful enough
 
80
 * that it should be included.
 
81
 */
 
82
static void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
 
83
{
 
84
    int bpp = surface->format->BytesPerPixel;
 
85
    /* Here p is the address to the pixel we want to set */
 
86
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
 
87
 
 
88
    switch(bpp) {
 
89
    case 1:
 
90
        *p = pixel;
 
91
        break;
 
92
 
 
93
    case 2:
 
94
        *(Uint16 *)p = pixel;
 
95
        break;
 
96
 
 
97
    case 3:
 
98
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
 
99
            p[0] = (pixel >> 16) & 0xff;
 
100
            p[1] = (pixel >> 8) & 0xff;
 
101
            p[2] = pixel & 0xff;
 
102
        } else {
 
103
            p[0] = pixel & 0xff;
 
104
            p[1] = (pixel >> 8) & 0xff;
 
105
            p[2] = (pixel >> 16) & 0xff;
 
106
        }
 
107
        break;
 
108
 
 
109
    case 4:
 
110
        *(Uint32 *)p = pixel;
 
111
        break;
 
112
    }
 
113
}
 
114
 
 
115
static void overlay_grid( int re_init, int ax, int ay)
 
116
{
 
117
 
 
118
  static SDL_Surface* grid_overlay;
 
119
 
 
120
  static int first_pass;
 
121
 
 
122
  int x= 0;
 
123
  int y= 0;
 
124
  SDL_Rect dst;
 
125
  Uint32 *pixel;
 
126
  SDL_PixelFormat* fmt;
 
127
 
 
128
  /* Need to convert back to screen coordinates */
 
129
  ax-= pl_pos.x;
 
130
  ay-= pl_pos.y;
 
131
  
 
132
  if( re_init == TRUE)
 
133
    {
 
134
      if( grid_overlay)
 
135
        SDL_FreeSurface( grid_overlay);
 
136
 
 
137
      first_pass= 0;
 
138
      grid_overlay= NULL;
 
139
    }
 
140
 
 
141
  if( grid_overlay == NULL)
 
142
    {
 
143
      grid_overlay= SDL_CreateRGBSurface( SDL_HWSURFACE|SDL_SRCALPHA, 
 
144
                                          use_config[CONFIG_MAPWIDTH]*map_image_size,
 
145
                                          use_config[CONFIG_MAPHEIGHT]*map_image_size,
 
146
                                          mapsurface->format->BitsPerPixel,
 
147
                                          mapsurface->format->Rmask,
 
148
                                          mapsurface->format->Gmask,
 
149
                                          mapsurface->format->Bmask,
 
150
                                          mapsurface->format->Amask);
 
151
      if( grid_overlay == NULL)
 
152
        do_SDL_error( "CreateRGBSurface", __FILE__, __LINE__);
 
153
 
 
154
      grid_overlay= SDL_DisplayFormatAlpha( grid_overlay);
 
155
 
 
156
      first_pass= 0;
 
157
    }
 
158
 
 
159
  /* 
 
160
   * If this is our first time drawing the grid, we need to build up the 
 
161
   * grid overlay
 
162
   */
 
163
  if( first_pass== 0)
 
164
    {
 
165
 
 
166
      /* Red pixels around the edge and along image borders
 
167
       * fully transparent pixels everywhere else
 
168
       */
 
169
      
 
170
      fmt= grid_overlay->format;
 
171
      for( x= 0; x < map_image_size*use_config[CONFIG_MAPWIDTH]; x++)
 
172
        {
 
173
          for( y= 0; y < map_image_size*use_config[CONFIG_MAPHEIGHT]; y++)
 
174
            {
 
175
              /* FIXME: Only works for 32 bit displays right now */
 
176
              pixel= (Uint32*)grid_overlay->pixels+y*grid_overlay->pitch/4+x;
 
177
 
 
178
              if( x == 0 || y == 0 || 
 
179
                  ((x % map_image_size) == 0) || ((y % map_image_size) == 0 ) ||
 
180
                  y == use_config[CONFIG_MAPHEIGHT]*map_image_size-1 || x == use_config[CONFIG_MAPWIDTH]*map_image_size -1 )
 
181
                {
 
182
                  *pixel= SDL_MapRGBA( fmt, 255, 0, 0, SDL_ALPHA_OPAQUE);
 
183
                }
 
184
              else 
 
185
                {
 
186
                  *pixel= SDL_MapRGBA( fmt, 0, 0, 0, SDL_ALPHA_TRANSPARENT);
 
187
                }
 
188
            }
 
189
        }
 
190
      first_pass= 1;
 
191
 
 
192
      /* 
 
193
       * If this is our first pass then we need to overlay the entire grid
 
194
       * now. Otherwise we just update the tile we are on
 
195
       */
 
196
      dst.x= 0;
 
197
      dst.y= 0;
 
198
      dst.w= map_image_size*use_config[CONFIG_MAPWIDTH];
 
199
      dst.h= map_image_size*use_config[CONFIG_MAPHEIGHT];
 
200
      SDL_BlitSurface( grid_overlay, NULL, mapsurface, &dst);
 
201
    } 
 
202
  else 
 
203
    {
 
204
      dst.x= ax* map_image_size;
 
205
      dst.y= ay* map_image_size;
 
206
      dst.w= map_image_size;
 
207
      dst.h= map_image_size;
 
208
      /* One to one pixel mapping of grid and mapsurface so we
 
209
       * can share the SDL_Rect
 
210
       */
 
211
      SDL_BlitSurface( grid_overlay, &dst, mapsurface, &dst);
 
212
    }
 
213
 
 
214
  return;
 
215
}
 
216
 
 
217
/*
 
218
 * Takes two args, the first is the GtkWindow to draw on, this should always
 
219
 * be 'drawingarea'. The second is a boolean, if 0 then the whole
 
220
 * SDL system in initialized or reinited if already run once before,
 
221
 * if non zero then only the lightmap is rebuilt, if we switch between
 
222
 * per-pixel or per-tile lighting 
 
223
 */
 
224
void init_SDL( GtkWidget* sdl_window, int just_lightmap)
 
225
{
 
226
 
 
227
    char SDL_windowhack[32];
 
228
 
 
229
    if( just_lightmap == 0) {
 
230
        g_assert( sdl_window != NULL);
 
231
        if( SDL_WasInit( SDL_INIT_VIDEO) != 0) {
 
232
            if( lightmap)
 
233
                SDL_FreeSurface( lightmap);
 
234
            if( mapsurface)
 
235
                SDL_FreeSurface( mapsurface);
 
236
            SDL_Quit();
 
237
        }
 
238
 
 
239
        /* 
 
240
         * SDL hack to tell SDL which xwindow to paint onto 
 
241
         */
 
242
        sprintf( SDL_windowhack, "SDL_WINDOWID=%ld",
 
243
               GDK_WINDOW_XWINDOW(sdl_window->window) );
 
244
        putenv( SDL_windowhack);
 
245
      
 
246
        if( SDL_Init( SDL_INIT_VIDEO) < 0)
 
247
        {
 
248
            LOG(LOG_CRITICAL,"gtk::init_SDL", "Could not initialize SDL: %s", SDL_GetError());
 
249
            gtk_main_quit();
 
250
        }
 
251
 
 
252
        mapsurface= SDL_SetVideoMode( map_image_size*use_config[CONFIG_MAPWIDTH], map_image_size*use_config[CONFIG_MAPHEIGHT], 0, 
 
253
                                    SDL_HWSURFACE|SDL_DOUBLEBUF);
 
254
 
 
255
        if( mapsurface == NULL)
 
256
        {
 
257
            do_SDL_error( "SetVideoMode", __FILE__, __LINE__);
 
258
        }
 
259
 
 
260
        if( fogmap)
 
261
            SDL_FreeSurface( fogmap);
 
262
 
 
263
        fogmap= SDL_CreateRGBSurface( SDL_HWSURFACE|SDL_SRCALPHA, map_image_size,
 
264
                                map_image_size,
 
265
                                mapsurface->format->BitsPerPixel,
 
266
                                mapsurface->format->Rmask,
 
267
                                mapsurface->format->Gmask,
 
268
                                mapsurface->format->Bmask,
 
269
                                mapsurface->format->Amask);
 
270
 
 
271
        if( fogmap == NULL)
 
272
        {
 
273
            do_SDL_error( "SDL_CreateRGBSurface", __FILE__, __LINE__);
 
274
        }
 
275
 
 
276
        /* 
 
277
         * This is a persurface alpha value, not an alpha channel value.
 
278
         * So this surface doesn't actually need a full alpha channel
 
279
         */
 
280
        if( SDL_SetAlpha( fogmap, SDL_SRCALPHA|SDL_RLEACCEL, 128) < 0)
 
281
        {
 
282
            do_SDL_error( "SDL_SetAlpha", __FILE__, __LINE__);
 
283
        }
 
284
    }
 
285
 
 
286
    if( just_lightmap != 0 && lightmap)
 
287
        SDL_FreeSurface( lightmap);
 
288
  
 
289
    lightmap= SDL_CreateRGBSurface( SDL_HWSURFACE|SDL_SRCALPHA, map_image_size,
 
290
                                  map_image_size,
 
291
                                  mapsurface->format->BitsPerPixel,
 
292
                                  mapsurface->format->Rmask,
 
293
                                  mapsurface->format->Gmask,
 
294
                                  mapsurface->format->Bmask,
 
295
                                  mapsurface->format->Amask);
 
296
    if( lightmap == NULL)
 
297
    {
 
298
        do_SDL_error( "SDL_CreateRGBSurface", __FILE__, __LINE__);
 
299
    }
 
300
  
 
301
    if(use_config[CONFIG_LIGHTING] != CFG_LT_TILE)
 
302
    {
 
303
        /* Convert surface to have a full alpha channel if we are doing
 
304
         * per-pixel lighting */
 
305
        lightmap= SDL_DisplayFormatAlpha( lightmap);
 
306
        if( lightmap == NULL)
 
307
        {
 
308
            do_SDL_error( "DisplayFormatAlpha", __FILE__, __LINE__);
 
309
        }
 
310
    }
 
311
 
 
312
    if(use_config[CONFIG_SHOWGRID] == TRUE)
 
313
    {
 
314
        overlay_grid( TRUE, 0, 0);
 
315
    }
 
316
    /* We make this a bit bigger than the actual map - thus, there
 
317
     * is a 1 space pad in all directions.  This enables us
 
318
     * to store a value in that area without having to do checks to
 
319
     * see if we are at the edge of the map - doing a store vs 4
 
320
     * checks is going to be much faster.
 
321
     */
 
322
    redrawbitmap = malloc(sizeof(char) * (MAP_MAX_SIZE +2)* (MAP_MAX_SIZE+2));
 
323
}
 
324
 
 
325
 
 
326
/* Draw a alpha square on lightmap. Topleft corner is at startx,starty. 
 
327
 * values for topleft, topright, bottomleft,bottomright corners are knowns
 
328
 * This use bilinear interpolation for other points. Width and heights are given
 
329
 * for surrouding known values square. Interpolation is done in a small square whose
 
330
 * coordinates are given by start{x|y} and end{x|y}
 
331
 * dest{x|y} is top-left corner in destination map.
 
332
 *                             Tchize 22 May 2004
 
333
 *
 
334
 * Note - profile shows this is a very costly function - of a small run,
 
335
 * 77% of the time of the cpu time for the client was in this function.
 
336
 */
 
337
 
 
338
void drawquarterlightmap_sdl(int tl, int tr, int bl, int br,                /*colors*/
 
339
                             int width, int height,                         /*color square size*/
 
340
                             int startx, int starty, int endx, int endy,    /*interpolation region*/
 
341
                             int destx, int desty){                         /*where in lightmap to save result*/
 
342
        int x,y;
 
343
        int top,bottom,val;
 
344
        for (x=startx;x<endx;x++){
 
345
                top= ((x*(tr-tl))/ width)+tl;    /*linear interpolation for top color*/
 
346
                bottom= ((x*(br-bl))/ width)+bl;  /*linear interpolation for bottom color*/
 
347
                for (y=starty;y<endy;y++){
 
348
                        val=((y*(bottom-top))/height)+top; /*linear interpolation between top and bottom*/
 
349
                        if (val>255)
 
350
                                val=255;
 
351
                        if (val<0)
 
352
                                val=0;
 
353
                        //printf("writing pel at %d,%d\n",destx+x,desty+y);
 
354
                        putpixel(lightmap, destx+x-startx, desty+y-starty,
 
355
                                SDL_MapRGBA(lightmap->format, 0, 0, 0, val));
 
356
                }
 
357
        }
 
358
}
 
359
 
 
360
/* Do the lighting on a per pixel basis.
 
361
 * x and y are coordinates on the drawable map surfaces (but in terms of
 
362
 * spaces, not pixels).  mx and my are indexes into the
 
363
 * the_map.cells[][] array.
 
364
 * All the below goes out and figures lighting for each pixel on
 
365
 * the space, and creates a surface (with alpha) that is then put on
 
366
 * top of the exiting map space.
 
367
 *
 
368
 * TODO: I think it is possible to greatly speed this up by using
 
369
 * pre-generated darkness masks.  Doing all the possibilities 
 
370
 * would be 3125 images (5 positions, each with 5 values, 5^5),
 
371
 * Doing it based on quadrants would only reduce that to 1024.
 
372
 * But I _think_ it may be possible to do this with just 64 images
 
373
 * (2^5 + one 90 degree rotation of the same) based on quadrants.
 
374
 * ie, do a 16x16 image with the 5 gradiants (0,64,128,255 at the
 
375
 * left, and each of those values at the right).  Then do the same
 
376
 * idea for top and bottom.  For any single quadrant, you would
 
377
 * then merge thse two values (which can be done with a fast blit),
 
378
 * corresponding to the right values, and you do the same thing for
 
379
 * the other four quadrants.  Note this only works so long as
 
380
 * 4 lighting values are used - if more are added, this quickly
 
381
 * breaks.  Also, if lighting colored effects are desired,
 
382
 * this also doesn't work very well.
 
383
 *
 
384
 * For now, I've just kept the old logic. MSW 2001-10-09
 
385
 */
 
386
 
 
387
/* See note below about ALPHA_FUDGE - used to adjust lighting effects some */
 
388
 
 
389
#define ALPHA_FUDGE(x)  (2*(x) / 3)
 
390
#define GENDARK(x,y) ( (((x)&(y) & 1) == 1)?255:0 )
 
391
void do_sdl_per_pixel_lighting(int x, int y, int mx, int my)
 
392
{
 
393
 
 
394
    int dark0, dark1, dark2, dark3, dark4;
 
395
    SDL_Rect dst;
 
396
 
 
397
    /* I use dark0 -> dark4 in the order to keep it similar to
 
398
     * the old code.
 
399
     */
 
400
    dark0 = the_map.cells[mx][my].darkness;
 
401
 
 
402
    if (y-1 < 0 || !the_map.cells[mx][my-1].have_darkness) dark1 = dark0;
 
403
    else dark1 = the_map.cells[mx][my-1].darkness;
 
404
 
 
405
    if (x+1 >= use_config[CONFIG_MAPWIDTH] || !the_map.cells[mx+1][my].have_darkness) dark2 = dark0;
 
406
    else dark2 = the_map.cells[mx+1][my].darkness;
 
407
 
 
408
    if (y+1 >= use_config[CONFIG_MAPHEIGHT] || !the_map.cells[mx][my+1].have_darkness) dark3 = dark0;
 
409
    else dark3 = the_map.cells[mx][my+1].darkness;
 
410
 
 
411
    if (x-1 < 0 || !the_map.cells[mx-1][my].have_darkness) dark4 = dark0;
 
412
    else dark4 = the_map.cells[mx-1][my].darkness;
 
413
 
 
414
    /* If they are all the same, processing is easy
 
415
     *
 
416
     * Note, the best lightining algorithm also uses diagonals
 
417
     * so we should check the diagonals are same too
 
418
     * We don't check for now, simply do all raw computation on best mode
 
419
     * Tchize 19 may 2004
 
420
     */
 
421
    if (dark0 == dark1 && dark0 == dark2 && dark0 == dark3 && dark0 == dark4 && (use_config[CONFIG_LIGHTING] != CFG_LT_PIXEL_BEST)) {
 
422
        dst.x = x * map_image_size;
 
423
        dst.y = y * map_image_size;
 
424
        dst.w = map_image_size;
 
425
        dst.h = map_image_size;
 
426
 
 
427
        if (dark0 == 255) {
 
428
            SDL_FillRect(mapsurface,&dst, SDL_MapRGB(mapsurface->format, 0, 0, 0));
 
429
        } else if (the_map.cells[mx][my].darkness != 0) {
 
430
            SDL_FillRect(lightmap,NULL, SDL_MapRGBA(lightmap->format, 0, 0, 0, the_map.cells[mx][my].darkness));
 
431
            SDL_BlitSurface(lightmap, NULL, mapsurface, &dst);
 
432
        }
 
433
        return;
 
434
    }
 
435
 
 
436
 
 
437
    if (use_config[CONFIG_LIGHTING] == CFG_LT_PIXEL ) {
 
438
        /* This almost works as well as the per pixel code below, but does have some various
 
439
         * artifacts in the drawing.  It uses the same logic as the per pixel code below,
 
440
         * bit since SDL does the blit, the alpha handling ends up being different
 
441
         * (I think it ends up being additive).  This results in the darkness being
 
442
         * darker, but you also don't get the smooth effects.  If you divide all the values
 
443
         * by 2 (change ALPHA_FUDGE), the blending is smooth, but now the things are not dark
 
444
         * enough, so the blending aganst solid black spaces does not look good.
 
445
         * The reason this code is of interest is that on my system, it is about 50%
 
446
         * faster than the code below (25 ms to darkness the church in the starting
 
447
         * town vs 50 ms for the code further down)
 
448
         * Setting ALPHA_FUDGE to 2/3 seems to reduce the artifacts described above
 
449
         * to fairly minimal levels, while still keeping things dark enough.
 
450
         * MSW 2001-10-12
 
451
         */
 
452
 
 
453
        int i;
 
454
 
 
455
        if (dark1 == dark0) {
 
456
            /* If we don't have usable darkness at the top, then this entire region
 
457
            * should be the same value.  Likewise, if the top value and center value
 
458
            * are the same, we can do the entire region.
 
459
            */
 
460
            dst.x=0;
 
461
            dst.y=0;
 
462
            dst.w = map_image_size;
 
463
            dst.h = map_image_half_size;
 
464
            SDL_FillRect(lightmap, &dst, SDL_MapRGBA(lightmap->format, 0, 0, 0, ALPHA_FUDGE(dark0)));
 
465
        }
 
466
        else for (i=0; i<map_image_half_size; i++) {
 
467
            /* Need to do it line by line */
 
468
 
 
469
            dst.x = 0;
 
470
            dst.y = i;
 
471
            dst.w = map_image_size;
 
472
            dst.h = 1;
 
473
            SDL_FillRect(lightmap, &dst, SDL_MapRGBA(lightmap->format, 0, 0, 0, 
 
474
                        ALPHA_FUDGE((map_image_half_size - i) * dark1 + i * dark0)/map_image_half_size));
 
475
 
 
476
        }
 
477
        /* All the following blocks are basically the same as above, just different
 
478
         * darkness areas.
 
479
         */
 
480
        if (dark3 == dark0) {
 
481
            dst.x=0;
 
482
            dst.y=map_image_half_size;
 
483
            dst.w = map_image_size;
 
484
            dst.h = map_image_half_size;
 
485
            SDL_FillRect(lightmap, &dst, SDL_MapRGBA(lightmap->format, 0, 0, 0, ALPHA_FUDGE(dark0)));
 
486
        }
 
487
        else for (i=map_image_half_size; i<map_image_size; i++) {
 
488
            /* Need to do it line by line */
 
489
 
 
490
            dst.x = 0;
 
491
            dst.y = i;
 
492
            dst.w = map_image_size;
 
493
            dst.h = 1;
 
494
            SDL_FillRect(lightmap, &dst, SDL_MapRGBA(lightmap->format, 0, 0, 0, 
 
495
                        ALPHA_FUDGE(dark0*(map_image_size-i) + dark3*(i-map_image_half_size)) / map_image_half_size));
 
496
        }
 
497
        /* Blit this to the screen now.  Otherwise, we need to look at the alpha values
 
498
         * and re-average.
 
499
         */
 
500
 
 
501
        dst.x= x * map_image_size; 
 
502
        dst.y= y * map_image_size;
 
503
        SDL_BlitSurface(lightmap, NULL, mapsurface, &dst);
 
504
 
 
505
        if (dark4 == dark0) {
 
506
            dst.x=0;
 
507
            dst.y=0;
 
508
            dst.w = map_image_half_size;
 
509
            dst.h = map_image_size;
 
510
            SDL_FillRect(lightmap, &dst, SDL_MapRGBA(lightmap->format, 0, 0, 0, ALPHA_FUDGE(dark0)));
 
511
        }
 
512
        else for (i=0; i<map_image_half_size; i++) {
 
513
            /* Need to do it line by line */
 
514
            dst.x = i;
 
515
            dst.y = 0;
 
516
            dst.w = 1;
 
517
            dst.h = map_image_size;
 
518
            SDL_FillRect(lightmap, &dst, SDL_MapRGBA(lightmap->format, 0, 0, 0,
 
519
                        ALPHA_FUDGE(dark4*(map_image_half_size-i) + dark0*i) / map_image_half_size));
 
520
        }
 
521
        if (dark2 == dark0) {
 
522
            dst.x=map_image_half_size;
 
523
            dst.y=0;
 
524
            dst.w = map_image_half_size;
 
525
            dst.h = map_image_size;
 
526
            SDL_FillRect(lightmap, &dst, SDL_MapRGBA(lightmap->format, 0, 0, 0, ALPHA_FUDGE(dark0)));
 
527
        }
 
528
        else for (i=map_image_half_size; i<map_image_size; i++) {
 
529
            /* Need to do it line by line */
 
530
 
 
531
            dst.x = i;
 
532
            dst.y = 0;
 
533
            dst.w = 1;
 
534
            dst.h = map_image_size;
 
535
            SDL_FillRect(lightmap, &dst, SDL_MapRGBA(lightmap->format, 0, 0, 0, 
 
536
                        ALPHA_FUDGE(dark0*(map_image_size-i) + dark2*(i-map_image_half_size)) / map_image_half_size));
 
537
        }
 
538
        dst.x= x * map_image_size; 
 
539
        dst.y= y * map_image_size;
 
540
        SDL_BlitSurface(lightmap, NULL, mapsurface, &dst);
 
541
    } else if (use_config[CONFIG_LIGHTING] == CFG_LT_PIXEL_BEST ) {
 
542
#if 0
 
543
        int dx,dy;
 
544
        static  int *darkx=NULL, *darky=NULL,darkx_allocated=0;
 
545
 
 
546
        /* Generated stored for the darkx[] array.  Do it dynamically, but
 
547
         * only allocate if the size needs to be expanded to keep performance
 
548
         * better.  darkx could be null in the initial case, but realloc should
 
549
         * just treat that as a malloc (so according to the man page)
 
550
         */
 
551
        if (map_image_size > darkx_allocated) {
 
552
            darkx = realloc(darkx, map_image_size * sizeof(int));
 
553
            darky = realloc(darky, map_image_size * sizeof(int));
 
554
            darkx_allocated = map_image_size;
 
555
        }
 
556
                        
 
557
        for( dx= 0; dx < map_image_half_size; dx++)
 
558
            darkx[dx]= (dark4*(map_image_half_size-dx) + dark0*dx) / map_image_half_size;
 
559
        for( dx= map_image_half_size; dx < map_image_size; dx++)
 
560
            darkx[dx] = (dark0*(map_image_size-dx) + dark2*(dx-map_image_half_size)) / map_image_half_size;
 
561
 
 
562
        for( dy= 0; dy < map_image_half_size; dy++)
 
563
            darky[dy]= (dark1*(map_image_half_size-dy) + dark0*dy) / map_image_half_size;
 
564
        for( dy= map_image_half_size; dy < map_image_size; dy++)
 
565
            darky[dy] = (dark0*(map_image_size-dy) + dark3*(dy-map_image_half_size)) / map_image_half_size;
 
566
 
 
567
        SDL_LockSurface( lightmap);
 
568
 
 
569
        for (dx=0; dx<map_image_size; dx++)
 
570
            for (dy=0; dy<map_image_size; dy++) 
 
571
                putpixel(lightmap, dx, dy, SDL_MapRGBA(lightmap->format, 0, 0, 0,(darkx[dx] + darky[dy])/2));
 
572
#else
 
573
        /*we need additionnal surrounding infos*/
 
574
        int dark5, dark6, dark7, dark8;
 
575
        if ( (y-1 < 0) || (x+1 >= use_config[CONFIG_MAPWIDTH])
 
576
                || !the_map.cells[mx+1][my-1].have_darkness) dark5 = (dark1+dark2)>>1; /*(fast div 2)*/
 
577
        else dark5 = the_map.cells[mx+1][my-1].darkness;
 
578
 
 
579
        if ( (x+1 >= use_config[CONFIG_MAPWIDTH]) 
 
580
                || (y+1 >= use_config[CONFIG_MAPHEIGHT])
 
581
                || !the_map.cells[mx+1][my+1].have_darkness) dark6 = (dark2+dark3)>>1;
 
582
        else dark6 = the_map.cells[mx+1][my+1].darkness;
 
583
 
 
584
        if ( (y+1 >= use_config[CONFIG_MAPHEIGHT]) || (x-1 < 0)
 
585
                || !the_map.cells[mx-1][my+1].have_darkness) dark7 = (dark3+dark4)>>1;
 
586
        else dark7 = the_map.cells[mx-1][my+1].darkness;
 
587
        
 
588
        if ( (x-1 < 0) || (y-1 < 0)
 
589
                || !the_map.cells[mx-1][my-1].have_darkness) dark8 = (dark4+dark1)>>1;
 
590
        else dark8 = the_map.cells[mx-1][my-1].darkness;
 
591
        /*upper left lightmap quarter*/
 
592
        drawquarterlightmap_sdl(dark8, dark1, dark4, dark0,                /*colors*/
 
593
                             map_image_size, map_image_size,               /*color square size*/
 
594
                             map_image_half_size, map_image_half_size, map_image_size, map_image_size,    /*interpolation region*/
 
595
                             0, 0);                         /*where in lightmap to save result*/
 
596
        /*upper right lightmap quarter*/
 
597
        drawquarterlightmap_sdl(dark1, dark5, dark0, dark2,                /*colors*/
 
598
                             map_image_size, map_image_size,               /*color square size*/
 
599
                             0, map_image_half_size, map_image_half_size, map_image_size,    /*interpolation region*/
 
600
                             map_image_half_size, 0);                         /*where in lightmap to save result*/
 
601
        /*bottom left lightmap quarter*/
 
602
        drawquarterlightmap_sdl(dark4, dark0, dark7, dark3,                /*colors*/
 
603
                             map_image_size, map_image_size,               /*color square size*/
 
604
                             map_image_half_size, 0, map_image_size, map_image_half_size,    /*interpolation region*/
 
605
                             0, map_image_half_size);                         /*where in lightmap to save result*/
 
606
        /*bottom right lightmap quarter*/
 
607
        drawquarterlightmap_sdl(dark0, dark2, dark3, dark6,                /*colors*/
 
608
                             map_image_size, map_image_size,               /*color square size*/
 
609
                             0, 0, map_image_half_size, map_image_half_size,    /*interpolation region*/
 
610
                             map_image_half_size, map_image_half_size);                         /*where in lightmap to save result*/
 
611
#endif
 
612
        dst.w= map_image_size;
 
613
        dst.h= map_image_size;
 
614
        dst.x= x * map_image_size; 
 
615
        dst.y= y * map_image_size;
 
616
        SDL_UnlockSurface(lightmap);
 
617
        SDL_BlitSurface(lightmap, NULL, mapsurface, &dst);      
 
618
    }
 
619
}
 
620
/* Draw anything in adjacent squares that could smooth on given square
 
621
 * mx,my square to smooth on. you should not call this function to
 
622
 * smooth on a 'completly black' square. (simply for visual result)
 
623
 * layer layer to examine (we smooth only one layer at a time)
 
624
 * dst place on the mapwindow to draw
 
625
 */
 
626
static void drawsmooth_sdl (int mx,int my,int layer,SDL_Rect dst){
 
627
    static int dx[8]={0,1,1,1,0,-1,-1,-1};
 
628
    static int dy[8]={-1,-1,0,1,1,1,0,-1};
 
629
    static int bweights[8]={2,0,4,0,8,0,1,0};
 
630
    static int cweights[8]={0,2,0,4,0,8,0,1};
 
631
    static int bc_exclude[8]={
 
632
                 1+2,/*north exclude northwest (bit0) and northeast(bit1)*/
 
633
                 0,
 
634
                 2+4,/*east exclude northeast and southeast*/
 
635
                 0,
 
636
                 4+8,/*and so on*/
 
637
                 0,
 
638
                 8+1,
 
639
                 0
 
640
                };
 
641
    int partdone[8]={0,0,0,0,0,0,0,0};
 
642
    int slevels[8];
 
643
    int sfaces[8];
 
644
    int i,lowest,weight,weightC;
 
645
    int emx,emy;
 
646
    int smoothface;
 
647
    int dosmooth=0;
 
648
    SDL_Rect src;
 
649
    src.w=dst.w;
 
650
    src.h=dst.h;
 
651
    if ( (the_map.cells[mx][my].heads[0].face==0)
 
652
         || !CAN_SMOOTH(the_map.cells[mx][my],layer) )
 
653
        return;
 
654
    for (i=0;i<8;i++){
 
655
        emx=mx+dx[i];
 
656
        emy=my+dy[i];
 
657
        if ( (emx<0) || (emy<0) || (the_map.x<=emx) || (the_map.y<=emy)){
 
658
            slevels[i]=0;
 
659
            sfaces[i]=0; /*black picture*/
 
660
        }
 
661
        if (the_map.cells[emx][emy].smooth[layer]<=the_map.cells[mx][my].smooth[layer]){
 
662
            slevels[i]=0;
 
663
            sfaces[i]=0; /*black picture*/
 
664
        }else{      
 
665
            slevels[i]=the_map.cells[emx][emy].smooth[layer];
 
666
            sfaces[i]=pixmaps[the_map.cells[emx][emy].heads[layer].face]->smooth_face;
 
667
            dosmooth=1;
 
668
        }                    
 
669
    }
 
670
    /* ok, now we have a list of smoothlevel higher than current square.
 
671
     * there are at most 8 different levels. so... let's check 8 times
 
672
     * for the lowest one (we draw from botto to top!).
 
673
     */
 
674
    lowest=-1;
 
675
    while (1){
 
676
        lowest = -1;
 
677
        for (i=0;i<8;i++){
 
678
            if ( (slevels[i]>0) && (!partdone[i]) &&
 
679
                ((lowest<0) || (slevels[i]<slevels[lowest]))
 
680
               )
 
681
                    lowest=i;    
 
682
        }
 
683
        if (lowest<0)
 
684
            break;   /*no more smooth to do on this square*/
 
685
        /*printf ("hey, must smooth something...%d\n",sfaces[lowest]);*/
 
686
        /*here we know 'what' to smooth*/
 
687
        /* we need to calculate the weight
 
688
         * for border and weight for corners.
 
689
         * then we 'markdone' 
 
690
         * the corresponding squares
 
691
         */
 
692
        /*first, the border, which may exclude some corners*/
 
693
        weight=0;
 
694
        weightC=15; /*works in backward. remove where there is nothing*/
 
695
        /*for (i=0;i<8;i++)
 
696
            cornermask[i]=1;*/
 
697
        for (i=0;i<8;i++){ /*check all nearby squares*/
 
698
            if ( (slevels[i]==slevels[lowest]) &&
 
699
                 (sfaces[i]==sfaces[lowest])){
 
700
                partdone[i]=1;
 
701
                weight=weight+bweights[i];
 
702
                weightC&=~bc_exclude[i];
 
703
            }else{
 
704
                /*must rmove the weight of a corner if not in smoothing*/
 
705
                weightC&=~cweights[i];
 
706
            }
 
707
            
 
708
        }
 
709
        /*We can't do this before since we need the partdone to be adjusted*/
 
710
        if (sfaces[lowest]<=0)
 
711
            continue;  /*Can't smooth black*/
 
712
        smoothface=sfaces[lowest];
 
713
        if (smoothface<=0){
 
714
            continue;  /*picture for smoothing not yet available*/
 
715
        }
 
716
        /* now, it's quite easy. We must draw using a 32x32 part of
 
717
         * the picture smoothface. 
 
718
         * This part is located using the 2 weights calculated: 
 
719
         * (32*weight,0) and (32*weightC,32)
 
720
         */
 
721
        if ( (!pixmaps[smoothface]->map_image) ||
 
722
             (pixmaps[smoothface] == pixmaps[0]))
 
723
            continue;   /*don't have the picture associated*/
 
724
        if (weight>0){
 
725
            src.x=map_image_size*weight;
 
726
            src.y=0;
 
727
            if (the_map.cells[mx][my].cleared) {
 
728
                if (SDL_BlitSurface(pixmaps[smoothface]->fog_image,
 
729
                        &src, mapsurface, &dst))
 
730
                    do_SDL_error( "BlitSurface", __FILE__, __LINE__);
 
731
            } else {
 
732
                if (SDL_BlitSurface(pixmaps[smoothface]->map_image,
 
733
                        &src, mapsurface, &dst))
 
734
                    do_SDL_error( "BlitSurface", __FILE__, __LINE__);
 
735
            }
 
736
        }
 
737
        if (weightC>0){
 
738
            src.x=map_image_size*weightC;
 
739
            src.y=map_image_size;
 
740
            if (the_map.cells[mx][my].cleared) {
 
741
                if (SDL_BlitSurface(pixmaps[smoothface]->fog_image,
 
742
                        &src, mapsurface, &dst))
 
743
                    do_SDL_error( "BlitSurface", __FILE__, __LINE__);
 
744
            } else {
 
745
                if (SDL_BlitSurface(pixmaps[smoothface]->map_image,
 
746
                        &src, mapsurface, &dst))
 
747
                    do_SDL_error( "BlitSurface", __FILE__, __LINE__);
 
748
            }
 
749
        }
 
750
 
 
751
 
 
752
    }/*while there's some smooth to do*/
 
753
}
 
754
 
 
755
/* This function tells if a specific square need to be redrawn
 
756
 * Reason for redrawing can be content change, smoothing change or 
 
757
 * surrounding lightning change. Conditions depend on type of 
 
758
 * lightning code used.
 
759
 *                              Tchize 22 May 2004
 
760
 *
 
761
 * Profile shows this is a big CPU user (50% in CFG_LT_PIXEL mode,
 
762
 * so I rewrote it to be much more efficient in the update_redrawbitmap()
 
763
 * function below.  Logic is a bit different, so not a straigtforward
 
764
 * replacement
 
765
 * MSW 2005-03-06
 
766
 */
 
767
int sdl_square_need_redraw(int mx, int my){
 
768
#define SDL_LIGHT_CHANGED(_x_,_y_) ( ( ( (_x_)<0) || ( (_y_)<0) || ( (_x_)>=the_map.x) || ( (_y_)>=the_map.y) )?0: the_map.cells[_x_][_y_].need_update )
 
769
 
 
770
    if ( (the_map.cells[mx][my].need_update) || (the_map.cells[mx][my].need_resmooth && use_config[CONFIG_SMOOTH]))
 
771
        return 1;
 
772
        
 
773
    if (use_config[CONFIG_LIGHTING] == CFG_LT_PIXEL){
 
774
        /*The fast per pixel uses 4 additionnal datas which may have changed:*/
 
775
        /*we suppose need_redraw -> lightr may have change. in future maybe we could add a need_relight toggle*/
 
776
        if (SDL_LIGHT_CHANGED(mx-1,my) ||
 
777
            SDL_LIGHT_CHANGED(mx,my-1) ||
 
778
            SDL_LIGHT_CHANGED(mx+1,my) ||
 
779
            SDL_LIGHT_CHANGED(mx,my+1))
 
780
            return 1;
 
781
    }
 
782
    if (use_config[CONFIG_LIGHTING] == CFG_LT_PIXEL_BEST){
 
783
        if (SDL_LIGHT_CHANGED(mx-1,my) ||
 
784
            SDL_LIGHT_CHANGED(mx,my-1) ||
 
785
            SDL_LIGHT_CHANGED(mx+1,my) ||
 
786
            SDL_LIGHT_CHANGED(mx,my+1) ||
 
787
            SDL_LIGHT_CHANGED(mx-1,my+1) ||
 
788
            SDL_LIGHT_CHANGED(mx-1,my-1) ||
 
789
            SDL_LIGHT_CHANGED(mx+1,my-1) ||
 
790
            SDL_LIGHT_CHANGED(mx+1,my+1) )
 
791
            return 1;
 
792
    }
 
793
    return 0; /*no need to redraw :)*/
 
794
}
 
795
 
 
796
/* update_redrawbitmap() - replacment of sdl_square_need_redraw logic.
 
797
 * use of sdl_square_need_redraw is relatively inefficient becuase
 
798
 * it is called for every space (hence function call overhead),
 
799
 * but also has 4 checks to make sure the neighbor space is within valid
 
800
 * range, and if non tile mode, performs that check at least 4 times
 
801
 * per space.
 
802
 * This is much more efficient, because our redrawbitmap array is
 
803
 * large enough we don't need those checks - we know we are always safe
 
804
 * to go one outside the bounds (hence, the +1 in the coordinate
 
805
 * values)
 
806
 */
 
807
static void update_redrawbitmap()
 
808
{
 
809
    int mx,my, x,y;
 
810
 
 
811
    memset(redrawbitmap, 0, (use_config[CONFIG_MAPWIDTH]+2) * (use_config[CONFIG_MAPHEIGHT]+2));
 
812
 
 
813
    for( x= 0; x<use_config[CONFIG_MAPWIDTH]; x++) {
 
814
        for(y = 0; y<use_config[CONFIG_MAPHEIGHT]; y++) {
 
815
            mx = x + pl_pos.x;
 
816
            my = y + pl_pos.y;
 
817
 
 
818
            /* Basically, we need to check the conditions that require this space.
 
819
             * to be redrawn.  We store this in redrawbitmap, because storing
 
820
             * in the_map[][].need_update would cause a cascade effect, of space
 
821
             * 1,0 need an update, so we thing 2,0 needs an update due to smoothing/
 
822
             * like, which causes 3,0 to be updated, etc.  Having our own
 
823
             * memory area allows the memset above, which is an optimized routine
 
824
             * to clear memory.
 
825
             */
 
826
            if (the_map.cells[mx][my].need_update) {
 
827
                redrawbitmap[x + 1 + (y+1) * use_config[CONFIG_MAPWIDTH]] = 1;
 
828
                /* If this space has changed, and using non tile lighting,
 
829
                 * we need to update the neighbor spaces.  Ideally, we'd
 
830
                 * have a flag just to denote lighting changes, since
 
831
                 * that is handled on a different surface anyways.
 
832
                 */
 
833
                if (use_config[CONFIG_LIGHTING] == CFG_LT_PIXEL || 
 
834
                    use_config[CONFIG_LIGHTING] == CFG_LT_PIXEL_BEST) {
 
835
                    /* This is where having redrawbitmap bigger pays off - don't have
 
836
                     * to check to see if values are within redrawbitmap is within bounds
 
837
                     */
 
838
                    redrawbitmap[x  + (y+1) * use_config[CONFIG_MAPWIDTH]] = 1;
 
839
                    redrawbitmap[x + 2 + (y+1) * use_config[CONFIG_MAPWIDTH]] = 1;
 
840
                    redrawbitmap[x + 1 + (y) * use_config[CONFIG_MAPWIDTH]] = 1;
 
841
                    redrawbitmap[x + 1 + (y+2) * use_config[CONFIG_MAPWIDTH]] = 1;
 
842
                }
 
843
                /* In best mode, have to update diaganols in addition*/
 
844
                if (use_config[CONFIG_LIGHTING] == CFG_LT_PIXEL_BEST) {
 
845
                    redrawbitmap[x  + (y) * use_config[CONFIG_MAPWIDTH]] = 1;
 
846
                    redrawbitmap[x + 2 + (y) * use_config[CONFIG_MAPWIDTH]] = 1;
 
847
                    redrawbitmap[x +  (y+2) * use_config[CONFIG_MAPWIDTH]] = 1;
 
848
                    redrawbitmap[x + 2 + (y+2) * use_config[CONFIG_MAPWIDTH]] = 1;
 
849
                }
 
850
            }
 
851
            else if (the_map.cells[mx][my].need_resmooth) {
 
852
                redrawbitmap[x + 1 + (y+1) * use_config[CONFIG_MAPWIDTH]] = 1;
 
853
            }
 
854
        }
 
855
    }
 
856
}
 
857
 
 
858
/* This generates a map in SDL mode.
 
859
 * 
 
860
 * I had to totally change the logic on how we do this in SDL mode - 
 
861
 * to support variable sized images, the old method of generating each
 
862
 * space does not work, as one space may spill over to the other.
 
863
 * Instead, we first blit the bottom layer, then the layer above
 
864
 * that, and so on.  This results in the map being drawn a bit
 
865
 * more correctly.  In fact, that logic actually isn't needed, as
 
866
 * with the new map commands, we know the offset and size of the
 
867
 * images.
 
868
 *
 
869
 * The logic here only redraws spaces that change.  The logic in the
 
870
 * common/commands.c files the odd layers with links for 'big images'.
 
871
 * for objects on these layers, we look at the size_x and size_y values
 
872
 * to determine the offset from which we should be blitting.
 
873
 *
 
874
 * Old notes, but left in:
 
875
 * The performance here is very good in most cases - about 30 ms (on my system)
 
876
 * is used just for my flip at the bottom of the function, drawing only what
 
877
 * is needed generally saves a lot of time (<15 ms in most cases) compared to the
 
878
 * 80-120 ms usually needed on a 15x15 map.
 
879
 */
 
880
 
 
881
void sdl_gen_map(int redraw) {
 
882
    int mx,my, layer,x,y, num_spaces=0, num_drawn=0;
 
883
    SDL_Rect dst, src;
 
884
    struct timeval tv1, tv2,tv3;
 
885
    long elapsed1, elapsed2;
 
886
 
 
887
    if (time_map_redraw)
 
888
        gettimeofday(&tv1, NULL);
 
889
 
 
890
    if (map_did_scroll) {
 
891
        map_updated=1;
 
892
    }
 
893
    /* If nothing changed, don't need to do all the code below */
 
894
    if (!redraw && !map_updated) return;
 
895
 
 
896
    map_updated=0;
 
897
    update_redrawbitmap();
 
898
 
 
899
    for( x= 0; x<use_config[CONFIG_MAPWIDTH]; x++) {
 
900
        for(y = 0; y<use_config[CONFIG_MAPHEIGHT]; y++) {
 
901
            num_spaces++;
 
902
            /* mx,my represent the spaces on the 'virtual' map (ie, the_map structure).
 
903
             * x and y (from the for loop) represent the visable screen.
 
904
             */
 
905
            mx = x + pl_pos.x;
 
906
            my = y + pl_pos.y;
 
907
 
 
908
            /* This will be updated in the for loop above for
 
909
             * whatever conditions that need this space to be redrawn
 
910
             */
 
911
            if (!redrawbitmap[x + 1 + (y+1) * use_config[CONFIG_MAPWIDTH]] && !redraw)
 
912
                continue;
 
913
 
 
914
            num_drawn++;
 
915
 
 
916
            /* First, we need to black out this space. */
 
917
            dst.x = x * map_image_size; dst.y = y* map_image_size;
 
918
            dst.w = map_image_size; 
 
919
            dst.h = map_image_size;
 
920
            SDL_FillRect(mapsurface, &dst, SDL_MapRGB(mapsurface->format, 0, 0, 0));
 
921
 
 
922
            /* now draw the different layers.  Only draw if using fog of war or the
 
923
             * space isn't clear.
 
924
             */
 
925
            if (use_config[CONFIG_FOGWAR] || !the_map.cells[mx][my].cleared) 
 
926
                for (layer=0; layer<MAXLAYERS; layer++) {
 
927
 
 
928
                    /* draw the tail first - this seems to get better results */
 
929
                    if (the_map.cells[mx][my].tails[layer].face &&
 
930
                        pixmaps[the_map.cells[mx][my].tails[layer].face]->map_image) {
 
931
 
 
932
                        /* add one to the size values to take into account the actual width of the space */
 
933
                        src.x = pixmaps[the_map.cells[mx][my].tails[layer].face]->map_width - 
 
934
                            (the_map.cells[mx][my].tails[layer].size_x + 1) * map_image_size;
 
935
                        src.y = pixmaps[the_map.cells[mx][my].tails[layer].face]->map_height - 
 
936
                            (the_map.cells[mx][my].tails[layer].size_y + 1) * map_image_size;
 
937
                        src.w = map_image_size;
 
938
                        src.h = map_image_size;
 
939
                        dst.x = x * map_image_size;
 
940
                        dst.y = y * map_image_size;
 
941
                        if (the_map.cells[mx][my].cleared) {
 
942
                            if (SDL_BlitSurface(pixmaps[the_map.cells[mx][my].tails[layer].face]->fog_image, 
 
943
                                &src, mapsurface, &dst))
 
944
                                    do_SDL_error( "BlitSurface", __FILE__, __LINE__);
 
945
                        } else {
 
946
                            if (SDL_BlitSurface(pixmaps[the_map.cells[mx][my].tails[layer].face]->map_image, 
 
947
                                &src, mapsurface, &dst))
 
948
                                    do_SDL_error( "BlitSurface", __FILE__, __LINE__);
 
949
                        }
 
950
                    }
 
951
                    /* Draw the head now - logic is pretty much exactly the same
 
952
                     * as that for the tail, except we know that we this is at the lower right,
 
953
                     * so we don't need to adjust the origin as much.
 
954
                     */
 
955
                    if (the_map.cells[mx][my].heads[layer].face && 
 
956
                        pixmaps[the_map.cells[mx][my].heads[layer].face]->map_image) {
 
957
 
 
958
                        src.x = pixmaps[the_map.cells[mx][my].heads[layer].face]->map_width - map_image_size;
 
959
                        src.y = pixmaps[the_map.cells[mx][my].heads[layer].face]->map_height - map_image_size;
 
960
                        src.w = map_image_size;
 
961
                        src.h = map_image_size;
 
962
                        dst.x = x * map_image_size;
 
963
                        dst.y = y * map_image_size;
 
964
                        if (the_map.cells[mx][my].cleared) {
 
965
                            if (SDL_BlitSurface(pixmaps[the_map.cells[mx][my].heads[layer].face]->fog_image,
 
966
                                &src, mapsurface, &dst))
 
967
                                    do_SDL_error( "BlitSurface", __FILE__, __LINE__);
 
968
                        } else {
 
969
                            if (SDL_BlitSurface(pixmaps[the_map.cells[mx][my].heads[layer].face]->map_image,
 
970
                                &src, mapsurface, &dst))
 
971
                                    do_SDL_error( "BlitSurface", __FILE__, __LINE__);
 
972
                        }
 
973
                        /*We have added either a head. Let's draw nearby squares coverts*/
 
974
                        if ( use_config[CONFIG_SMOOTH])
 
975
                            drawsmooth_sdl (mx,my,layer,dst);
 
976
                    }
 
977
                    /* Sometimes, it may happens we need to draw the smooth while there
 
978
                     * is nothing to draw at that layer (but there was something at lower
 
979
                     * layers). This is handled here. The else part is to take into account
 
980
                     * cases where the smooth as already been handled 2 code lines before
 
981
                     */
 
982
                    else if ( use_config[CONFIG_SMOOTH] &&
 
983
                             the_map.cells[mx][my].need_resmooth )
 
984
                    drawsmooth_sdl (mx,my,layer,dst);
 
985
                } /* else for processing the layers */
 
986
 
 
987
            /* Do final logic for this map space */
 
988
            the_map.cells[mx][my].need_update=0;
 
989
 
 
990
            if (use_config[CONFIG_LIGHTING] == CFG_LT_TILE) {
 
991
                dst.x = x * map_image_size;
 
992
                dst.y = y * map_image_size;
 
993
                dst.w = map_image_size;
 
994
                dst.h = map_image_size;
 
995
 
 
996
                /* Note - Instead of using a lightmap, I just fillrect
 
997
                 * directly onto the map surface - I would think this should be
 
998
                 * faster
 
999
                 */
 
1000
                if (the_map.cells[mx][my].darkness == 255) {
 
1001
                    SDL_FillRect(mapsurface,&dst, SDL_MapRGB(mapsurface->format, 0, 0, 0));
 
1002
                } else if (the_map.cells[mx][my].darkness != 0) {
 
1003
                    SDL_SetAlpha(lightmap, SDL_SRCALPHA|SDL_RLEACCEL, the_map.cells[mx][my].darkness);
 
1004
                    SDL_BlitSurface(lightmap, NULL, mapsurface, &dst);
 
1005
                }
 
1006
            } else if (use_config[CONFIG_LIGHTING] == CFG_LT_PIXEL || use_config[CONFIG_LIGHTING] == CFG_LT_PIXEL_BEST) {
 
1007
                do_sdl_per_pixel_lighting(x, y, mx, my);
 
1008
            }
 
1009
        } /* For y spaces */
 
1010
    } /* for x spaces */
 
1011
    if (time_map_redraw)
 
1012
        gettimeofday(&tv2, NULL);
 
1013
 
 
1014
    SDL_Flip(mapsurface);
 
1015
 
 
1016
    if (time_map_redraw) {
 
1017
        gettimeofday(&tv3, NULL);
 
1018
        elapsed1 = (tv2.tv_sec - tv1.tv_sec)*1000000 + (tv2.tv_usec - tv1.tv_usec);
 
1019
        elapsed2 = (tv3.tv_sec - tv2.tv_sec)*1000000 + (tv3.tv_usec - tv2.tv_usec);
 
1020
 
 
1021
        /* I care about performance for 'long' updates, so put the check in to make
 
1022
         * these a little more noticable */
 
1023
        if ((elapsed1 + elapsed2)>10000)
 
1024
            LOG(LOG_INFO,"gtk::sdl_gen_map","gen took %7ld, flip took %7ld, total = %7ld",
 
1025
                    elapsed1, elapsed2, elapsed1 + elapsed2);
 
1026
    }
 
1027
    /*fprintf(stderr,"sdl_gen_map: %d/%d spaces drawn\n", num_drawn, num_spaces);*/
 
1028
} /* sdl_gen_map function */
 
1029
 
 
1030
void sdl_mapscroll(int dx, int dy)
 
1031
{
 
1032
    map_updated=1;
 
1033
    map_did_scroll=1;
 
1034
 
 
1035
    /* Don't sdl_gen_map should take care of the redraw */
 
1036
 
 
1037
    /* a copy of what pngximage does except sdl specfic
 
1038
     * mapsurface->pitch is the length of a scanline in bytes 
 
1039
     * including alignment padding
 
1040
     */
 
1041
    SDL_LockSurface( mapsurface);
 
1042
    if( dy < 0) {
 
1043
        int offset= mapsurface->pitch * (-dy*map_image_size);
 
1044
        memmove( mapsurface->pixels + offset, mapsurface->pixels, 
 
1045
                     mapsurface->pitch * (mapsurface->h + dy*map_image_size) );
 
1046
    }
 
1047
    else if( dy > 0) {
 
1048
        int offset= mapsurface->pitch * (dy*map_image_size);
 
1049
        memmove( mapsurface->pixels,  mapsurface->pixels + offset,
 
1050
                     mapsurface->pitch * (mapsurface->h - dy*map_image_size) );
 
1051
    }
 
1052
 
 
1053
    if (dx) {
 
1054
        int y;
 
1055
        for( y= 0; y < mapsurface->h; y++) {
 
1056
            if( dx < 0) {
 
1057
                char* start_of_row= mapsurface->pixels + mapsurface->pitch * y;
 
1058
                int offset= ( mapsurface->format->BytesPerPixel * map_image_size * -dx);
 
1059
                memmove( start_of_row + offset, start_of_row,
 
1060
                             mapsurface->pitch - offset);
 
1061
            }
 
1062
            else {
 
1063
                char* start_of_row= mapsurface->pixels + mapsurface->pitch * y; 
 
1064
                int offset= ( mapsurface->format->BytesPerPixel * map_image_size * dx);
 
1065
                memmove( start_of_row, start_of_row + offset,
 
1066
                             mapsurface->pitch - offset);
 
1067
            }
 
1068
        }
 
1069
    }
 
1070
    SDL_UnlockSurface( mapsurface);
 
1071
    map_did_scroll= 1;
 
1072
}
 
1073
 
 
1074
            
 
1075
 
 
1076
#endif
 
1077