5 #include <SDL/SDL_getenv.h>
13 #include "../dirnames.h"
14 #include "graphics.fdh"
16 NXSurface
*screen
= NULL
; // created from SDL's screen
17 static NXSurface
*drawtarget
= NULL
; // target of DrawRect etc; almost always screen
18 bool use_palette
= false; // true if we are in an indexed-color video mode
21 const NXColor
DK_BLUE(0, 0, 0x21); // the popular dk blue backdrop color
22 const NXColor
BLACK(0, 0, 0); // pure black, only works if no colorkey
23 const NXColor
CLEAR(0, 0, 0); // the transparent/colorkey color
25 static bool is_fullscreen
= false;
26 static int current_res
= -1;
28 bool Graphics::init(int resolution
)
36 screen_bpp
= 16; // the default
39 const SDL_VideoInfo
*info
;
41 // it's faster if we create the SDL screen at the bpp of the real screen.
42 // max fps went from 120 to 160 on my X11 system this way.
43 if ((info
= SDL_GetVideoInfo()))
45 stat("videoinfo: desktop bpp %d", info
->vfmt
->BitsPerPixel
);
46 if (info
->vfmt
->BitsPerPixel
> 8)
47 screen_bpp
= info
->vfmt
->BitsPerPixel
;
54 if (SetResolution(resolution
, false))
66 void Graphics::close()
68 stat("Graphics::Close()");
73 void c------------------------------() {}
76 bool Graphics::InitVideo()
78 SDL_Surface
*sdl_screen
;
80 if (drawtarget
== screen
) drawtarget
= NULL
;
81 if (screen
) delete screen
;
83 uint32_t flags
= SDL_SWSURFACE
| SDL_HWPALETTE
;
84 if (is_fullscreen
) flags
|= SDL_FULLSCREEN
;
87 putenv((char *)"SDL_VIDEO_CENTERED=1");
90 stat("SDL_SetVideoMode: %dx%d @ %dbpp", SCREEN_WIDTH
*SCALE
, SCREEN_HEIGHT
*SCALE
, screen_bpp
);
91 sdl_screen
= SDL_SetVideoMode(SCREEN_WIDTH
*SCALE
, SCREEN_HEIGHT
*SCALE
, screen_bpp
, flags
);
94 staterr("Graphics::InitVideo: error setting video mode");
98 if (use_palette
&& !(sdl_screen
->flags
& SDL_HWPALETTE
))
100 staterr("Graphics::InitVideo: failed to obtain exclusive access to hardware palette");
104 SDL_WM_SetCaption("NXEngine", NULL
);
105 SDL_ShowCursor(is_fullscreen
== false);
107 screen
= new NXSurface(sdl_screen
, false);
108 if (!drawtarget
) drawtarget
= screen
;
112 bool Graphics::FlushAll()
114 stat("Graphics::FlushAll()");
116 Sprites::FlushSheets();
118 map_flush_graphics();
119 return font_reload();
122 void Graphics::SetFullscreen(bool enable
)
124 if (is_fullscreen
!= enable
)
126 is_fullscreen
= enable
;
128 Graphics::FlushAll();
132 // change the video mode to one of the available resolution codes, currently:
133 // 0 - 640x480, Fullscreen
134 // 1 - Windowed scale x1 (320x240)
135 // 2 - Windowed scale x2 (640x480)
136 // 3 - Windowed scale x3 (960x720)
137 bool Graphics::SetResolution(int r
, bool restoreOnFailure
)
139 stat("Graphics::SetResolution(%d)", r
);
140 if (r
== current_res
)
143 int old_res
= current_res
;
148 is_fullscreen
= true;
153 is_fullscreen
= false;
157 stat("Setting scaling %d and fullscreen=%s", factor
, is_fullscreen
? "yes":"no");
158 NXSurface::SetScale(factor
);
160 if (Graphics::InitVideo())
162 staterr("Switch to resolution %d failed!", r
);
164 if (restoreOnFailure
)
166 staterr("Trying to recover old mode %d.", r
, old_res
);
167 if (Graphics::SetResolution(old_res
, false))
169 staterr("Fatal error: vidmode recovery failed!!!");
176 if (Graphics::FlushAll()) return 1;
180 // return a pointer to a null-terminated list of available resolutions.
181 const char **Graphics::GetResolutions()
183 static const char *res_str
[] =
186 "320x240", "640x480", "960x720",
194 void c------------------------------() {}
197 // copy a sprite into the current tileset.
198 // used to obtain the images for the star tiles (breakable blocks),
199 // and for animated motion tiles in Waterway.
200 void Graphics::CopySpriteToTile(int spr
, int tileno
, int offset_x
, int offset_y
)
202 NXRect srcrect
, dstrect
;
204 srcrect
.x
= (sprites
[spr
].frame
[0].dir
[0].sheet_offset
.x
+ offset_x
);
205 srcrect
.y
= (sprites
[spr
].frame
[0].dir
[0].sheet_offset
.y
+ offset_y
);
209 dstrect
.x
= (tileno
% 16) * TILE_W
;
210 dstrect
.y
= (tileno
/ 16) * TILE_H
;
214 NXSurface
*tileset
= Tileset::GetSurface();
215 NXSurface
*spritesheet
= Sprites::get_spritesheet(sprites
[spr
].spritesheet
);
217 if (tileset
&& spritesheet
)
219 // blank out the old tile data with clear
220 tileset
->FillRect(&dstrect
, CLEAR
);
222 // copy the sprite over
223 BlitSurface(spritesheet
, &srcrect
, tileset
, &dstrect
);
228 void Graphics::ShowLoadingScreen()
231 char fname
[MAXPATHLEN
];
233 sprintf(fname
, "%s/Loading.pbm", data_dir
);
234 if (loading
.LoadImage(fname
))
237 int x
= (SCREEN_WIDTH
/ 2) - (loading
.Width() / 2);
238 int y
= (SCREEN_HEIGHT
/ 2) - loading
.Height();
241 DrawSurface(&loading
, x
, y
);
246 void c------------------------------() {}
249 // blit from one surface to another, just like SDL_BlitSurface.
250 void Graphics::BlitSurface(NXSurface
*src
, NXRect
*srcrect
, NXSurface
*dst
, NXRect
*dstrect
)
252 dst
->DrawSurface(src
, dstrect
->x
, dstrect
->y
, \
253 srcrect
->x
, srcrect
->y
, srcrect
->w
, srcrect
->h
);
257 void c------------------------------() {}
260 // draw the entire surface to the screen at the given coordinates.
261 void Graphics::DrawSurface(NXSurface
*src
, int x
, int y
)
263 drawtarget
->DrawSurface(src
, x
, y
);
267 // blit the specified portion of the surface to the screen
268 void Graphics::DrawSurface(NXSurface
*src
, \
269 int dstx
, int dsty
, int srcx
, int srcy
, int wd
, int ht
)
271 drawtarget
->DrawSurface(src
, dstx
, dsty
, srcx
, srcy
, wd
, ht
);
275 // blit the specified surface across the screen in a repeating pattern
276 void Graphics::BlitPatternAcross(NXSurface
*sfc
, int x_dst
, int y_dst
, int y_src
, int height
)
278 drawtarget
->BlitPatternAcross(sfc
, x_dst
, y_dst
, y_src
, height
);
282 void c------------------------------() {}
285 void Graphics::DrawRect(int x1
, int y1
, int x2
, int y2
, NXColor color
)
287 drawtarget
->DrawRect(x1
, y1
, x2
, y2
, color
);
290 void Graphics::FillRect(int x1
, int y1
, int x2
, int y2
, NXColor color
)
292 drawtarget
->FillRect(x1
, y1
, x2
, y2
, color
);
295 void Graphics::DrawPixel(int x
, int y
, NXColor color
)
297 drawtarget
->DrawPixel(x
, y
, color
);
300 void Graphics::ClearScreen(NXColor color
)
302 drawtarget
->Clear(color
.r
, color
.g
, color
.b
);
306 void c------------------------------() {}
309 void Graphics::DrawRect(int x1
, int y1
, int x2
, int y2
, uint8_t r
, uint8_t g
, uint8_t b
)
311 drawtarget
->DrawRect(x1
, y1
, x2
, y2
, r
, g
, b
);
314 void Graphics::FillRect(int x1
, int y1
, int x2
, int y2
, uint8_t r
, uint8_t g
, uint8_t b
)
316 drawtarget
->FillRect(x1
, y1
, x2
, y2
, r
, g
, b
);
319 void Graphics::DrawPixel(int x
, int y
, uint8_t r
, uint8_t g
, uint8_t b
)
321 drawtarget
->DrawPixel(x
, y
, r
, g
, b
);
324 void Graphics::ClearScreen(uint8_t r
, uint8_t g
, uint8_t b
)
326 drawtarget
->Clear(r
, g
, b
);
330 void c------------------------------() {}
333 void Graphics::set_clip_rect(int x
, int y
, int w
, int h
)
335 drawtarget
->set_clip_rect(x
, y
, w
, h
);
338 void Graphics::set_clip_rect(NXRect
*rect
)
340 drawtarget
->set_clip_rect(rect
);
343 void Graphics::clear_clip_rect()
345 drawtarget
->clear_clip_rect();
349 void c------------------------------() {}
352 // change the target surface of operation like DrawRect to something
353 // other than the screen.
354 void Graphics::SetDrawTarget(NXSurface
*surface
)
356 drawtarget
= surface
;