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

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