1 /*
2 * OpenBOR - http://www.LavaLit.com
3 * -----------------------------------------------------------------------
4 * All rights reserved, see LICENSE in OpenBOR root for details.
5 *
6 * Copyright (c) 2004 - 2011 OpenBOR Team
7 */
8
9 #include <SDL_framerate.h>
10 #include <math.h>
11 #include "types.h"
12 #include "video.h"
13 #include "vga.h"
14 #include "screen.h"
15 #include "sdlport.h"
16 #include "opengl.h"
17 #include "openbor.h"
18 #include "gfxtypes.h"
19 #include "gfx.h"
20
21 extern int videoMode;
22
23 #if GP2X || DARWIN || DINGOO || WII
24 #define SKIP_CODE
25 #endif
26
27 #ifndef SKIP_CODE
28 #include "pngdec.h"
29 #include "../resources/OpenBOR_Icon_32x32_png.h"
30 #endif
31
32 FPSmanager framerate_manager;
33 s_videomodes stored_videomodes;
34 static SDL_Surface *screen = NULL;
35 static SDL_Surface *bscreen = NULL;
36 static SDL_Surface *bscreen2 = NULL;
37 #ifdef DINGOO
38 static SDL_Surface *screen_dingoo = NULL;
39 #endif
40 static SDL_Color colors[256];
41 static int bytes_per_pixel = 1;
42 int stretch = 0;
43 int opengl = 0; // OpenGL backend currently in use?
44 int nativeWidth, nativeHeight; // monitor resolution used in fullscreen mode
45 u8 pDeltaBuffer[480 * 2592];
46
initSDL()47 void initSDL()
48 {
49 const SDL_VideoInfo* video_info;
50 int init_flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK;
51
52 #ifdef CUSTOM_SIGNAL_HANDLER
53 init_flags |= SDL_INIT_NOPARACHUTE;
54 #endif
55
56 if(SDL_Init(init_flags) < 0)
57 {
58 printf("SDL Failed to Init!!!! (%s)\n", SDL_GetError());
59 borExit(0);
60 }
61 SDL_ShowCursor(SDL_DISABLE);
62 atexit(SDL_Quit);
63 #ifndef SKIP_CODE
64 SDL_WM_SetCaption("OpenBOR", NULL);
65 SDL_WM_SetIcon((SDL_Surface*)pngToSurface((void*)openbor_icon_32x32_png.data), NULL);
66 #endif
67 #if WIN || LINUX && !DARWIN && !defined(GLES)
68 if(SDL_GL_LoadLibrary(NULL) < 0)
69 {
70 printf("Warning: couldn't load OpenGL library (%s)\n", SDL_GetError());
71 }
72 #endif
73
74 // Store the monitor's current resolution before setting the video mode for the first time
75 video_info = SDL_GetVideoInfo();
76 #ifndef GP2X
77 nativeWidth = video_info->current_w;
78 nativeHeight = video_info->current_h;
79 #endif
80
81 SDL_initFramerate(&framerate_manager);
82 SDL_setFramerate(&framerate_manager, 200);
83 }
84
85 static unsigned masks[4][4] = {{0,0,0,0},{0x1F,0x07E0,0xF800,0},{0xFF,0xFF00,0xFF0000,0},{0xFF,0xFF00,0xFF0000,0}};
86
video_set_mode(s_videomodes videomodes)87 int video_set_mode(s_videomodes videomodes)
88 {
89 stored_videomodes = videomodes;
90
91 if(screen) SDL_FreeAndNullVideoSurface(screen);
92 if(bscreen) { SDL_FreeSurface(bscreen); bscreen=NULL; }
93 if(bscreen2) { SDL_FreeSurface(bscreen2); bscreen2=NULL; }
94
95 // try OpenGL initialization first
96 if((savedata.usegl[savedata.fullscreen]) && video_gl_set_mode(videomodes)) return 1;
97 else opengl = 0;
98
99 // FIXME: OpenGL surfaces aren't freed when switching from OpenGL to SDL
100
101 bytes_per_pixel = videomodes.pixel;
102 if(videomodes.hRes==0 && videomodes.vRes==0)
103 {
104 Term_Gfx();
105 return 0;
106 }
107
108 if(savedata.screen[videoMode][0])
109 {
110 #ifdef DINGOO
111 screen_dingoo = SDL_SetVideoMode(videomodes.hRes*savedata.screen[videoMode][0],videomodes.vRes*savedata.screen[videoMode][0],16,SDL_SWSURFACE);
112 screen = SDL_AllocSurface(SDL_SWSURFACE,videomodes.hRes*savedata.screen[videoMode][0],videomodes.vRes*savedata.screen[videoMode][0], 16,0,0,0,0);
113 #else
114 screen = SDL_SetVideoMode(videomodes.hRes*savedata.screen[videoMode][0],videomodes.vRes*savedata.screen[videoMode][0],16,savedata.fullscreen?(SDL_SWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN):(SDL_SWSURFACE|SDL_DOUBLEBUF));
115 #endif
116 SDL_ShowCursor(SDL_DISABLE);
117 bscreen = SDL_AllocSurface(SDL_SWSURFACE, videomodes.hRes, videomodes.vRes, 8*bytes_per_pixel, masks[bytes_per_pixel-1][0], masks[bytes_per_pixel-1][1], masks[bytes_per_pixel-1][2], masks[bytes_per_pixel-1][3]); // 24bit mask
118 bscreen2 = SDL_AllocSurface(SDL_SWSURFACE, videomodes.hRes+4, videomodes.vRes+8, 16, masks[1][2], masks[1][1], masks[1][0], masks[1][3]);
119 Init_Gfx(565, 16);
120 memset(pDeltaBuffer, 0x00, 1244160);
121 if(bscreen==NULL || bscreen2==NULL) return 0;
122 }
123 else
124 {
125 if(bytes_per_pixel>1)
126 {
127 bscreen = SDL_AllocSurface(SDL_SWSURFACE, videomodes.hRes, videomodes.vRes, 8*bytes_per_pixel, masks[bytes_per_pixel-1][0], masks[bytes_per_pixel-1][1], masks[bytes_per_pixel-1][2], masks[bytes_per_pixel-1][3]); // 24bit mask
128 if(!bscreen) return 0;
129 }
130 #ifdef DINGOO
131 screen_dingoo = SDL_SetVideoMode(videomodes.hRes,videomodes.vRes,16,SDL_SWSURFACE);
132 screen = SDL_AllocSurface(SDL_SWSURFACE,videomodes.hRes,videomodes.vRes, 8*bytes_per_pixel,0,0,0,0);
133 #else
134 screen = SDL_SetVideoMode(videomodes.hRes,videomodes.vRes,8*bytes_per_pixel,savedata.fullscreen?(SDL_SWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN):(SDL_SWSURFACE|SDL_DOUBLEBUF));
135 #endif
136 SDL_ShowCursor(SDL_DISABLE);
137 }
138
139 if(bytes_per_pixel==1)
140 {
141 SDL_SetColors(screen,colors,0,256);
142 if(bscreen) SDL_SetColors(bscreen,colors,0,256);
143 }
144
145 if(screen==NULL) return 0;
146
147 video_clearscreen();
148 return 1;
149 }
150
video_fullscreen_flip()151 void video_fullscreen_flip()
152 {
153 size_t w, h;
154 if(savedata.usegl) { video_gl_fullscreen_flip(); return; }
155 savedata.fullscreen ^= 1;
156
157 if(savedata.fullscreen)
158 {
159 // OpenGL has better fullscreen than SDL
160 if(video_set_mode(stored_videomodes)) return;
161 }
162 else if(opengl)
163 {
164 // switch from OpenGL fullscreen to SDL windowed
165 if(video_set_mode(stored_videomodes)) return;
166 return;
167 }
168
169 // switch between SDL fullscreen and SDL windowed
170 if(screen) {
171 w = screen->w;
172 h = screen->h;
173 SDL_FreeVideoSurface(screen);
174 } else {
175 w = 320;
176 h = 240;
177 }
178
179 if(savedata.screen[videoMode][0])
180 screen = SDL_SetVideoMode(w,h,16,savedata.fullscreen?(SDL_SWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN):(SDL_SWSURFACE|SDL_DOUBLEBUF));
181 else
182 screen = SDL_SetVideoMode(w,h,8*bytes_per_pixel,savedata.fullscreen?(SDL_SWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN):(SDL_SWSURFACE|SDL_DOUBLEBUF));
183 SDL_ShowCursor(SDL_DISABLE);
184 SDL_SetColors(screen,colors,0,256);
185 if(bscreen) SDL_SetColors(bscreen,colors,0,256);
186 }
187
188 //16bit, scale 2x 4x 8x ...
_stretchblit(SDL_Surface * src,SDL_Rect * srcrect,SDL_Surface * dst,SDL_Rect * dstrect)189 void _stretchblit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect)
190 {
191 SDL_Rect rect;
192 int dst_x, dst_y, dst_w, dst_h, dst_row, src_row;
193 int i;
194 Uint16* psrc, *pdst;
195
196 if(!srcrect)
197 {
198 rect.x = rect.y = 0;
199 rect.w = src->w;
200 rect.h = src->h;
201 srcrect = ▭
202 }
203 dst_w = savedata.screen[videoMode][0] * srcrect->w;
204 dst_h = savedata.screen[videoMode][0] * srcrect->h;
205 if(!dstrect)
206 {
207 dst_x = dst_y = 0;
208 if(dst_w>dst->w) dst_w = dst->w;
209 if(dst_h>dst->h) dst_h = dst->h;
210 }
211 else
212 {
213 dst_x = dstrect->x;
214 dst_y = dstrect->y;
215 if(dst_w>dstrect->w) dst_w = dstrect->w;
216 if(dst_h>dstrect->h) dst_h = dstrect->h;
217 }
218 psrc = (Uint16*)src->pixels + srcrect->x + srcrect->y * src->pitch/2;
219 pdst = (Uint16*)dst->pixels + dst_x + dst_y*dst->pitch/2;
220 dst_row = dst->pitch/2;
221 src_row = src->pitch/2;
222 while(dst_h>0)
223 {
224 for(i=0; i<dst_w; i++)
225 {
226 *(pdst + i) = *(psrc+(i/savedata.screen[videoMode][0]));
227 }
228
229 for(i=1, pdst += dst_row; i<savedata.screen[videoMode][0] && dst_h; i++, dst_h--, pdst += dst_row)
230 {
231 memcpy(pdst, pdst-dst_row, dst_w<<1);
232 }
233 dst_h--;
234 psrc += src_row;
235 }
236 }
237
video_copy_screen(s_screen * src)238 int video_copy_screen(s_screen* src)
239 {
240 unsigned char *sp;
241 char *dp;
242 int width, height, linew, slinew;
243 int h;
244 SDL_Surface* ds = NULL;
245 SDL_Rect rectdes, rectsrc;
246
247 // use video_gl_copy_screen if in OpenGL mode
248 if(opengl) return video_gl_copy_screen(src);
249
250 width = screen->w;
251 if(width > src->width) width = src->width;
252 height = screen->h;
253 if(height > src->height) height = src->height;
254 if(!width || !height) return 0;
255 h = height;
256
257 if(bscreen)
258 {
259 rectdes.x = rectdes.y = 0;
260 rectdes.w = width*savedata.screen[videoMode][0]; rectdes.h = height*savedata.screen[videoMode][0];
261 if(bscreen2) {rectsrc.x = 2; rectsrc.y = 4;}
262 else {rectsrc.x = 0; rectsrc.y = 0;}
263 rectsrc.w = width; rectsrc.h = height;
264 if(SDL_MUSTLOCK(bscreen)) SDL_LockSurface(bscreen);
265 }
266
267 // Copy to linear video ram
268 if(SDL_MUSTLOCK(screen)) SDL_LockSurface(screen);
269
270 sp = (unsigned char*)src->data;
271 ds = (bscreen?bscreen:screen);
272 dp = ds->pixels;
273
274 linew = width*bytes_per_pixel;
275 slinew = src->width*bytes_per_pixel;
276
277 do{
278 memcpy(dp, sp, linew);
279 sp += slinew;
280 dp += ds->pitch;
281 }while(--h);
282
283 if(SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen);
284
285 if(bscreen)
286 {
287 if(SDL_MUSTLOCK(bscreen)) SDL_UnlockSurface(bscreen);
288 if(bscreen2) SDL_BlitSurface(bscreen, NULL, bscreen2, &rectsrc);
289 else SDL_BlitSurface(bscreen, NULL, screen, &rectsrc);
290 if(bscreen2)
291 {
292 if(bscreen2 && SDL_MUSTLOCK(bscreen2)) SDL_LockSurface(bscreen2);
293 if(SDL_MUSTLOCK(screen)) SDL_LockSurface(screen);
294
295 if(savedata.screen[videoMode][0]==2) (*GfxBlitters[(int)savedata.screen[videoMode][1]])((u8*)bscreen2->pixels+bscreen2->pitch*4+4, bscreen2->pitch, pDeltaBuffer+bscreen2->pitch, (u8*)screen->pixels, screen->pitch, screen->w>>1, screen->h>>1);
296 else _stretchblit(bscreen2, &rectsrc, screen, &rectdes);
297
298 if(SDL_MUSTLOCK(bscreen2)) SDL_UnlockSurface(bscreen2);
299 if(SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen);
300 }
301 }
302 #ifdef DINGOO
303 SDL_BlitSurface(screen,NULL,screen_dingoo,NULL);
304 SDL_Flip(screen_dingoo);
305 #else
306 SDL_Flip(screen);
307 #endif
308
309 #if WIN || LINUX
310 SDL_framerateDelay(&framerate_manager);
311 #endif
312
313 return 1;
314 }
315
video_clearscreen()316 void video_clearscreen()
317 {
318 if(opengl) { video_gl_clearscreen(); return; }
319
320 if(SDL_MUSTLOCK(screen)) SDL_LockSurface(screen);
321 memset(screen->pixels, 0, screen->pitch*screen->h);
322 if(SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen);
323 if(bscreen)
324 {
325 if(SDL_MUSTLOCK(bscreen)) SDL_LockSurface(bscreen);
326 memset(bscreen->pixels, 0, bscreen->pitch*bscreen->h);
327 if(SDL_MUSTLOCK(bscreen)) SDL_UnlockSurface(bscreen);
328 }
329 }
330
video_stretch(int enable)331 void video_stretch(int enable)
332 {
333 if(screen || opengl) video_clearscreen();
334 stretch = enable;
335 }
336
vga_vwait(void)337 void vga_vwait(void)
338 {
339 #ifdef GP2X
340 gp2x_video_wait_vsync();
341 #else
342 static int prevtick = 0;
343 int now = SDL_GetTicks();
344 int wait = 1000/60 - (now - prevtick);
345 if (wait>0)
346 {
347 SDL_Delay(wait);
348 }
349 else SDL_Delay(1);
350 prevtick = now;
351 #endif
352 }
353
vga_setpalette(unsigned char * palette)354 void vga_setpalette(unsigned char* palette)
355 {
356 int i;
357 video_gl_setpalette(palette);
358 for(i=0;i<256;i++){
359 colors[i].r=palette[0];
360 colors[i].g=palette[1];
361 colors[i].b=palette[2];
362 palette+=3;
363 }
364 if(!opengl)
365 {
366 SDL_SetColors(screen,colors,0,256);
367 if(bscreen) SDL_SetColors(bscreen,colors,0,256);
368 }
369 }
370
371 // TODO: give this function a boolean (int) return type denoting success/failure
vga_set_color_correction(int gm,int br)372 void vga_set_color_correction(int gm, int br)
373 {
374 if(opengl) video_gl_set_color_correction(gm, br);
375 }
376
377