source: abuse/trunk/src/sdlport/video-overlay.cpp @ 129

Last change on this file since 129 was 129, checked in by Sam Hocevar, 14 years ago
  • Get rid of jmalloc and replace it with standard malloc. Modern operating systems certainly perform a lot better than this custom implementation, and we have superior tools (eg. valgrind) to debug and profile memory usage without interfering with the code itself.
File size: 10.4 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 2001 Anthony Kruize <trandor@labyrinth.net.au>
4 *
5 *  This program is free software; you can redistribute it and/or modify
6 *  it under the terms of the GNU General Public License as published by
7 *  the Free Software Foundation; either version 2 of the License, or
8 *  (at your option) any later version.
9 *
10 *  This program is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *  GNU General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with this program; if not, write to the Free Software Foundation,
17 *  Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
18 */
19
20#include "config.h"
21
22#include <SDL.h>
23
24#include "filter.hpp"
25#include "globals.hpp"
26#include "system.h"
27#include "video.hpp"
28#include "macs.hpp"
29#include "image.hpp"
30#include "setup.h"
31
32SDL_Surface *window = NULL, *surface = NULL;
33SDL_Overlay *overlay;
34image *screen = NULL;
35unsigned char current_background;
36
37extern unsigned int xres, yres;
38extern palette *lastl;
39extern flags_struct flags;
40
41unsigned short win_xres, win_yres;
42int win_xscale, win_yscale;
43
44
45// Forward declarations
46void blit_surface( SDL_Rect *srcrect, SDL_Rect *dstrect );
47
48//
49// set_mode()
50// Set the video mode
51//
52void set_mode( int mode, int argc, char **argv )
53{
54    const SDL_VideoInfo *vidInfo;
55    int vidFlags = SDL_HWPALETTE;
56
57    // Check for video capabilities
58    vidInfo = SDL_GetVideoInfo();
59    if( vidInfo->hw_available )
60    {
61        vidFlags |= SDL_HWSURFACE;
62    }
63    else
64    {
65        vidFlags |= SDL_SWSURFACE;
66    }
67    if( flags.fullscreen )
68    {
69        vidFlags |= SDL_FULLSCREEN;
70    }
71    if( flags.doublebuf )
72    {
73        vidFlags |= SDL_DOUBLEBUF;
74    }
75
76    // Calculate the window scale
77    win_xscale = (flags.xres << 16) / xres;
78    win_yscale = (flags.yres << 16) / yres;
79
80    // Set the icon for this window.  Looks nice on taskbars etc.
81    SDL_WM_SetIcon( SDL_LoadBMP("abuse.bmp"), NULL );
82
83    // Create the window
84    window = SDL_SetVideoMode( flags.xres, flags.yres, 0, vidFlags );
85    if( window == NULL )
86    {
87        printf( "Video : Unable to set video mode : %s\n", SDL_GetError() );
88        exit( 1 );
89    }
90
91    // Use overlays because they are faster for scaling
92    if( flags.overlay )
93    {
94        overlay = SDL_CreateYUVOverlay( xres, yres, SDL_UYVY_OVERLAY, window );
95    }
96
97    // Create the screen image
98    screen = new image( xres, yres, NULL, 2 );
99    if( screen == NULL )
100    {
101        // Our screen image is no good, we have to bail.
102        printf( "Video : Unable to create screen image.\n" );
103        exit( 1 );
104    }
105    screen->clear();
106
107    // Create our 8-bit surface
108    surface = SDL_CreateRGBSurface( SDL_SWSURFACE, window->w, window->h, 8, 0xff, 0xff, 0xff, 0xff );
109    if( surface == NULL )
110    {
111        // Our surface is no good, we have to bail.
112        printf( "Video : Unable to create 8-bit surface.\n" );
113        exit( 1 );
114    }
115
116    printf( "Video : Using a window of %dx%d %dbpp\n", window->w, window->h, window->format->BitsPerPixel );
117
118    // Set the window caption
119    SDL_WM_SetCaption( "Abuse-SDL", "Abuse-SDL" );
120
121    // Grab and hide the mouse cursor
122    SDL_ShowCursor( 0 );
123    if( flags.grabmouse )
124    {
125        SDL_WM_GrabInput( SDL_GRAB_ON );
126    }
127
128    update_dirty( screen );
129}
130
131//
132// close_graphics()
133// Shutdown the video mode
134//
135void close_graphics()
136{
137    if( lastl )
138    {
139        delete lastl;
140    }
141    lastl = NULL;
142    // Free our 8-bit surface
143    if( surface )
144    {
145        SDL_FreeSurface( surface );
146    }
147    // Free our overlay
148    if( overlay )
149    {
150        SDL_FreeYUVOverlay( overlay );
151    }
152    delete screen;
153}
154
155// put_part_image()
156// Draw only dirty parts of the image
157//
158void put_part_image( image *im, int x, int y, int x1, int y1, int x2, int y2 )
159{
160    int xs, xe, ys, ye;
161    SDL_Rect srcrect, dstrect;
162    int ii, jj;
163    int srcx, srcy, xstep, ystep;
164    Uint8 *dpixel;
165    Uint16 dinset;
166    int dest_addr, line_width;
167
168    if( y > (int)yres || x > (int)xres )
169    {
170        return;
171    }
172    CHECK( x1 >= 0 && x2 >= x1 && y1 >= 0 && y2 >= y1 );
173
174    // Adjust if we are trying to draw off the screen
175    if( x < 0 )
176    {
177        x1 += -x;
178        x = 0;
179    }
180    srcrect.x = x1;
181    if( x + ( x2 - x1 ) >= xres )
182    {
183        xe = xres - x + x1 - 1;
184    }
185    else
186    {
187        xe = x2;
188    }
189    if( y < 0 )
190    {
191        y1 += -y;
192        y = 0;
193    }
194    srcrect.y = y1;
195    if( y + ( y2 - y1 ) >= yres )
196    {
197        ye = yres - y + y1 - 1;
198    }
199    else
200    {
201        ye = y2;
202    }
203    if( srcrect.x >= xe || srcrect.y >= ye )
204        return;
205
206    if( SDL_LockYUVOverlay( overlay ) == -1 )
207    {
208        // we failed to lock
209        printf( "ERROR - Failed to lock overlay.\n" );
210        return;
211    }
212
213    // This is our old copying code, left here for now just in case I still nee it
214    // Set up our blit rectangle
215    dstrect.w = xe - xs;
216    dstrect.h = ye - ys;
217    dstrect.x = x;
218    dstrect.y = y;
219    line_width = xe - xs + 1;
220
221    if( SDL_LockYUVOverlay( overlay ) == -1 )
222    {
223        // we failed to lock
224        printf( "ERROR - Failed to lock overlay.\n" );
225        return;
226    }
227
228    // fill buffer with current surface
229/*    for( int ii = ys; ii <= ye; ii++ )
230    {
231//        dest_addr = ( (dstrect.y + ii - ys) * screen_width ) + dstrect.x;
232        dest_addr = ( (dstrect.y + ii - ys) * overlay->pitches[0] ) + dstrect.x;
233//        memcpy( &((char *)(surface->pixels))[dest_addr], im->scan_line( ii ) + xs, line_width );
234//        memcpy( &((char *)(overlay->pixels))[dest_addr], im->scan_line( ii ) + xs, line_width );
235    }*/
236    char blah = 0xff;
237    for( int ii = 0; ii < overlay->pitches[0] * 2; ii++ )
238    memcpy( &((char *)(overlay->pixels))[ii], ((char *)(&blah)), 1 );
239
240    SDL_UnlockYUVOverlay( overlay );
241
242/*    // Scale the image onto the surface
243    srcrect.w = xe - srcrect.x;
244    srcrect.h = ye - srcrect.y;
245    dstrect.x = ((x * win_xscale) >> 16);
246    dstrect.y = ((y * win_yscale) >> 16);
247    dstrect.w = ((srcrect.w * win_xscale) >> 16);
248    dstrect.h = ((srcrect.h * win_yscale) >> 16);
249
250    xstep = (srcrect.w << 16) / dstrect.w;
251    ystep = (srcrect.h << 16) / dstrect.h;
252
253    srcy = ((srcrect.y) << 16);
254    dinset = ((surface->w - dstrect.w)) * surface->format->BytesPerPixel;
255
256    // Lock the surface if necessary
257    if( SDL_MUSTLOCK( surface ) )
258    {
259        SDL_LockSurface( surface );
260    }
261    dpixel = (Uint8 *)surface->pixels;
262    dpixel += (dstrect.x + ((dstrect.y) * surface->w)) * surface->format->BytesPerPixel;
263
264    for( ii = 0; ii < dstrect.h; ii++ )
265    {
266        srcx = (srcrect.x << 16);
267        for( jj = 0; jj < dstrect.w; jj++ )
268        {
269            memcpy( dpixel, im->scan_line( (srcy >> 16) ) + ((srcx >> 16) * surface->format->BytesPerPixel), surface->format->BytesPerPixel );
270            dpixel += surface->format->BytesPerPixel;
271            srcx += xstep;
272        }
273        dpixel += dinset;
274        srcy += ystep;
275    }
276
277    // Now unlock the surface if we locked it.
278    if( SDL_MUSTLOCK( surface ) )
279    {
280        SDL_UnlockSurface( surface );
281    } */
282
283    // Now blit the surface
284    blit_surface( &dstrect, &dstrect );
285}
286
287//
288// put_image()
289// Draw the entire image
290//
291void put_image( image * im, int x, int y )
292{
293    put_part_image( im, x, y, 0, 0, im->width() - 1, im->height() - 1 );
294}
295
296//
297// update_dirty_window()
298// Update the dirty parts of the window
299//
300void update_dirty_window( image *im, int xoff, int yoff )
301{
302    int count;
303    dirty_rect *dr, *q;
304    CHECK( im->special ); // make sure the image has the ability to contain dirty areas
305    if( im->special->keep_dirt == 0 )
306    {
307        put_image( im, xoff, yoff );
308    }
309    else
310    {
311        count = im->special->dirties.number_nodes();
312        if( !count )
313            return;  // if nothing to update, return
314        dr = (dirty_rect *)( im->special->dirties.first() );
315        while( count > 0 )
316        {
317            put_part_image( im, xoff + dr->dx1, yoff + dr->dy1, dr->dx1, dr->dy1, dr->dx2 + 1, dr->dy2 + 1 );
318            q = dr;
319            dr = (dirty_rect *)( dr->next() );
320            im->special->dirties.unlink( ( linked_node *)q );
321            delete q;
322            count--;
323        }
324    }
325}
326
327//
328// update_dirty()
329// Update the dirty parts of the image
330//
331void update_dirty( image *im, int xoff, int yoff )
332{
333    update_dirty_window( im, xoff, yoff );
334}
335
336//
337// make_page()
338//
339void image::make_page( short width, short height, unsigned char *page_buffer )
340{
341    if( page_buffer )
342    {
343        data = page_buffer;
344    }
345    else
346    {
347        data = (unsigned char *)malloc(width * height);
348    }
349}
350
351//
352// delete_page()
353//
354void image::delete_page()
355{
356    if( !special || !special->static_mem )
357    {
358        free( data );
359    }
360}
361
362//
363// load()
364// Set the palette
365//
366void palette::load()
367{
368    if( lastl )
369    {
370        delete lastl;
371    }
372    lastl = copy();
373
374    // Force to only 256 colours.
375    // Shouldn't be needed, but best to be safe.
376    if( ncolors > 256 )
377    {
378        ncolors = 256;
379    }
380
381    SDL_Color colors[ncolors];
382    for( int ii = 0; ii < ncolors; ii++ )
383    {
384        colors[ii].r = red(ii);
385        colors[ii].g = green(ii);
386        colors[ii].b = blue(ii);
387    }
388    SDL_SetColors( surface, colors, 0, ncolors );
389    if( window->format->BitsPerPixel == 8 )
390    {
391        SDL_SetColors( window, colors, 0, ncolors );
392    }
393
394    // Now redraw the surface
395    blit_surface( NULL, NULL );
396}
397
398//
399// load_nice()
400//
401void palette::load_nice()
402{
403    load();
404}
405
406// ---- support functions ----
407
408void blit_surface( SDL_Rect *srcrect, SDL_Rect *dstrect)
409{
410    SDL_Surface *cvtsfc = SDL_ConvertSurface( surface, window->format, SDL_HWSURFACE );
411    if( cvtsfc == NULL )
412    {
413        // Our convert surface died...bad :(
414        return;
415    }
416
417    if( flags.overlay )
418    {
419        SDL_Rect or;
420        or.x = 0;
421        or.y = 0;
422        or.w = window->w;
423        or.h = window->h;
424        SDL_DisplayYUVOverlay( overlay, &or );
425    }
426
427//    SDL_BlitSurface( cvtsfc, srcrect, window, dstrect );
428    SDL_FreeSurface( cvtsfc );
429
430    // Flip the backbuffer to the front
431    if( flags.doublebuf )
432    {
433        SDL_Flip( window );
434    }
435    else
436    {
437        if( dstrect == NULL )
438        {
439            SDL_UpdateRect( window, 0, 0, 0, 0 );
440        }
441        else
442        {
443            SDL_UpdateRect( window, dstrect->x, dstrect->y, dstrect->w, dstrect->h );
444        }
445    }
446}
Note: See TracBrowser for help on using the repository browser.