NXEngine v1.0.0.5
[NXEngine.git] / graphics / graphics.cpp
blob7c9a60fbf9b57f54e2dbccf48caf8f29241a6536
2 // graphics routines
3 #include <SDL/SDL.h>
4 #ifndef __SDLSHIM__
5 #include <SDL/SDL_getenv.h>
6 #endif
8 #include <stdlib.h>
9 #include "../config.h"
10 #include "graphics.h"
11 #include "tileset.h"
12 #include "sprites.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
19 int screen_bpp;
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)
30 if (use_palette)
32 screen_bpp = 8;
34 else
36 screen_bpp = 16; // the default
38 #ifndef __SDLSHIM__
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;
49 #endif
52 palette_reset();
54 if (SetResolution(resolution, false))
55 return 1;
57 if (Tileset::Init())
58 return 1;
60 if (Sprites::Init())
61 return 1;
63 return 0;
66 void Graphics::close()
68 stat("Graphics::Close()");
69 SDL_ShowCursor(true);
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;
86 #ifndef __SDLSHIM__
87 putenv((char *)"SDL_VIDEO_CENTERED=1");
88 #endif
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);
92 if (!sdl_screen)
94 staterr("Graphics::InitVideo: error setting video mode");
95 return 1;
98 if (use_palette && !(sdl_screen->flags & SDL_HWPALETTE))
100 staterr("Graphics::InitVideo: failed to obtain exclusive access to hardware palette");
101 exit(1);
104 SDL_WM_SetCaption("NXEngine", NULL);
105 SDL_ShowCursor(is_fullscreen == false);
107 screen = new NXSurface(sdl_screen, false);
108 if (!drawtarget) drawtarget = screen;
109 return 0;
112 bool Graphics::FlushAll()
114 stat("Graphics::FlushAll()");
115 palette_reset();
116 Sprites::FlushSheets();
117 Tileset::Reload();
118 map_flush_graphics();
119 return font_reload();
122 void Graphics::SetFullscreen(bool enable)
124 if (is_fullscreen != enable)
126 is_fullscreen = enable;
127 InitVideo();
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)
141 return 0;
143 int old_res = current_res;
144 int factor;
146 if (r == 0)
148 is_fullscreen = true;
149 factor = 2;
151 else
153 is_fullscreen = false;
154 factor = r;
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!!!");
173 return 1;
176 if (Graphics::FlushAll()) return 1;
177 return 0;
180 // return a pointer to a null-terminated list of available resolutions.
181 const char **Graphics::GetResolutions()
183 static const char *res_str[] =
185 "Fullscreen",
186 "320x240", "640x480", "960x720",
187 NULL
190 return res_str;
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);
206 srcrect.w = TILE_W;
207 srcrect.h = TILE_H;
209 dstrect.x = (tileno % 16) * TILE_W;
210 dstrect.y = (tileno / 16) * TILE_H;
211 dstrect.w = TILE_W;
212 dstrect.h = 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()
230 NXSurface loading;
231 char fname[MAXPATHLEN];
233 sprintf(fname, "%s/Loading.pbm", data_dir);
234 if (loading.LoadImage(fname))
235 return;
237 int x = (SCREEN_WIDTH / 2) - (loading.Width() / 2);
238 int y = (SCREEN_HEIGHT / 2) - loading.Height();
240 ClearScreen(BLACK);
241 DrawSurface(&loading, x, y);
242 drawtarget->Flip();
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;