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

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