]> Shamusworld >> Repos - stargem2/blob - src/video.cpp
e3ad1b7abeab38f16632511d209560eb864c7406
[stargem2] / src / video.cpp
1 //
2 // VIDEO.CPP: SDL/local hardware specific video routines
3 //
4 // by James L. Hammons
5 //
6
7 #include "video.h"
8
9 //#include "SDL.h"
10 #include <string.h>     // Why??? (for memset, etc... Lazy!) Dunno why, but this just strikes me as wrong...
11 #include <malloc.h>
12 #include "sdlemu_opengl.h"
13 #include "log.h"
14 #include "settings.h"
15 #include "icon.h"
16
17 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
18 #define MASK_R 0xFF000000
19 #define MASK_G 0x00FF0000
20 #define MASK_B 0x0000FF00
21 #define MASK_A 0x000000FF
22 #else
23 #define MASK_R 0x000000FF
24 #define MASK_G 0x0000FF00
25 #define MASK_B 0x00FF0000
26 #define MASK_A 0xFF000000
27 #endif
28
29 //#define TEST_ALPHA_BLENDING
30
31 // Exported global variables (actually, these are LOCAL global variables, EXPORTED...)
32
33 SDL_Surface * surface, * mainSurface, * someAlphaSurface;
34 Uint32 mainSurfaceFlags;
35 uint32 * scrBuffer = NULL;
36 SDL_Joystick * joystick;
37
38 //
39 // Prime SDL and create surfaces
40 //
41 bool InitVideo(void)
42 {
43         // Set up SDL library
44         if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE) < 0)
45         {
46                 WriteLog("Video: Could not initialize the SDL library: %s\n", SDL_GetError());
47                 return false;
48         }
49
50         // Get proper info about the platform we're running on...
51         const SDL_VideoInfo * info = SDL_GetVideoInfo();
52
53         if (!info)
54         {
55                 WriteLog("Video: SDL is unable to get the video info: %s\n", SDL_GetError());
56                 return false;
57         }
58
59         WriteLog("Video: Hardware is%s available...\n", (info->hw_available ? "" : " NOT"));
60         WriteLog("Video: Hardware blit is%s available...\n", (info->blit_hw ? "" : " NOT"));
61
62         if (settings.useOpenGL)
63         {
64                 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF | SDL_OPENGL;
65                 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
66 //We want 32BPP, so force the issue...
67                 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
68                 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
69                 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
70         }
71         else
72         {
73                 mainSurfaceFlags = SDL_DOUBLEBUF;
74
75                 if (info->hw_available)
76                         mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE;
77
78                 if (info->blit_hw)
79                         mainSurfaceFlags |= SDL_HWACCEL;
80         }
81
82         if (settings.fullscreen)
83                 mainSurfaceFlags |= SDL_FULLSCREEN;
84
85         // Create the primary SDL display (32 BPP)
86         if (settings.useOpenGL)
87                 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH * 2, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
88         else
89                 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
90
91         if (mainSurface == NULL)
92         {
93                 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
94                 return false;
95         }
96
97         // Set icon (mainly for Win32 target--though seems to work under KDE as well...!)
98         SDL_Surface * iconSurf = SDL_CreateRGBSurfaceFrom(icon, 32, 32, 32, 128, 
99                 MASK_R, MASK_G, MASK_B, MASK_A);
100         SDL_WM_SetIcon(iconSurf, NULL);
101         SDL_FreeSurface(iconSurf);
102
103         SDL_WM_SetCaption("StarGem2", "StarGem2");
104
105         // Create the secondary SDL display (32 BPP) that we use directly
106         surface = SDL_CreateRGBSurface(SDL_SWSURFACE, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, MASK_R, MASK_G, MASK_B, MASK_A);
107 /*WriteLog("Video: Created secondary surface with attributes:\n\n");
108 WriteLog("\tWidth, height: %u x %u\n", surface->w, surface->h);
109 WriteLog("\t        Pitch: %u\n", surface->pitch);
110 WriteLog("\t      Palette: %08X\n", surface->format->palette);
111 WriteLog("\t          BPP: %u\n", surface->format->BitsPerPixel);
112 WriteLog("\t      BytesPP: %u\n", surface->format->BytesPerPixel);
113 WriteLog("\t        RMask: %08X\n", surface->format->Rmask);
114 WriteLog("\t        GMask: %08X\n", surface->format->Gmask);
115 WriteLog("\t        BMask: %08X\n", surface->format->Bmask);
116 WriteLog("\t        AMask: %08X\n", surface->format->Amask);
117 WriteLog("\n");//*/
118
119         if (surface == NULL)
120         {
121                 WriteLog("Video: Could not create secondary SDL surface: %s\n", SDL_GetError());
122                 return false;
123         }
124
125         if (settings.useOpenGL)
126                 sdlemu_init_opengl(surface, mainSurface, 1 /*method*/,
127                         settings.glFilter /*texture type (linear, nearest)*/,
128                         0 /* Automatic bpp selection based upon src */);
129
130         // Initialize Joystick support under SDL
131 /*      if (settings.useJoystick)
132         {
133                 if (SDL_NumJoysticks() <= 0)
134                 {
135                         settings.useJoystick = false;
136                         WriteLog("Video: No joystick(s) or joypad(s) detected on your system. Using keyboard...\n");
137                 }
138                 else
139                 {
140                         if ((joystick = SDL_JoystickOpen(settings.joyport)) == 0)
141                         {
142                                 settings.useJoystick = false;
143                                 WriteLog("Video: Unable to open a Joystick on port: %d\n", (int)settings.joyport);
144                         }
145                         else
146                                 WriteLog("Video: Using: %s\n", SDL_JoystickName(settings.joyport));
147                 }
148         }//*/
149
150         // Set up the scrBuffer
151         scrBuffer = (uint32 *)surface->pixels;  // Kludge--And shouldn't have to lock since it's a software surface...
152 //needed? Dunno. Mebbe an SDL function instead?
153 //      memset(scrBuffer, 0x00, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint32));
154
155 #ifdef TEST_ALPHA_BLENDING
156 //Here's some code to test alpha blending...
157 //Well whaddya know, it works. :-)
158         someAlphaSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 30, 30, 32,
159                 MASK_R, MASK_G, MASK_B, MASK_A);
160
161         for(int i=0; i<30; i++)
162         {
163                 for(int j=0; j<30; j++)
164                 {
165                         uint32 color = (uint32)(((double)(i * j) / (29.0 * 29.0)) * 255.0);
166                         color = (color << 24) | 0x00FF00FF;
167                         ((uint32 *)someAlphaSurface->pixels)[(j * 30) + i] = color;
168                 }
169         }
170 //End test code
171 #endif
172
173         WriteLog("Video: Successfully initialized.\n");
174         return true;
175 }
176
177 //
178 // Free various SDL components
179 //
180 void VideoDone(void)
181 {
182         if (settings.useOpenGL)
183                 sdlemu_close_opengl();
184
185         SDL_JoystickClose(joystick);
186         SDL_FreeSurface(surface);
187         SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER);
188         SDL_Quit();
189 }
190
191
192
193 #if 0
194 ///
195
196 #include "SDL.h"
197 #include <string.h>     // Why??? (for memset, etc... Lazy!) Dunno why, but this just strikes me as wrong...
198 #include <malloc.h>
199 #include "sdlemu_opengl.h"
200 #include "types.h"
201 #include "log.h"
202 #include "settings.h"
203 #include "video.h"
204
205 // External global variables
206
207 SDL_Surface * surface, * mainSurface;
208 Uint32 mainSurfaceFlags;
209 uint8 * backbuffer;
210 SDL_Joystick * joystick;
211 uint8 color[16];
212 uint32 palette[256];
213
214 //
215 // Prime SDL and create surfaces
216 //
217 bool InitVideo(void)
218 {
219         // Set up SDL library
220         if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE) < 0)
221         {
222                 WriteLog("Video: Could not initialize the SDL library: %s\n", SDL_GetError());
223                 return false;
224         }
225
226         // Get proper info about the platform we're running on...
227         const SDL_VideoInfo * info = SDL_GetVideoInfo();
228
229         if (!info)
230         {
231                 WriteLog("Video: SDL is unable to get the video info: %s\n", SDL_GetError());
232                 return false;
233         }
234
235         if (1)//(vjs.useOpenGL)
236         {
237                 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF | SDL_OPENGL;
238                 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
239         }
240         else
241         {
242                 if (info->hw_available)
243                 {
244                         mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF;
245                         WriteLog("Video: Hardware available...\n");
246                 }
247
248                 if (info->blit_hw)
249                 {
250                         mainSurfaceFlags |= SDL_HWACCEL;
251                         WriteLog("Video: Hardware blit available...\n");
252                 }
253         }
254
255 //      if (vjs.fullscreen)
256 //              mainSurfaceFlags |= SDL_FULLSCREEN;
257
258         if (0)//(!vjs.useOpenGL)
259                 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
260         else
261                 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH * 2, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
262
263         if (mainSurface == NULL)
264         {
265                 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
266                 return false;
267         }
268
269         SDL_WM_SetCaption("StarGem2", "StarGem2");
270
271         // Create the primary SDL display (8 BPP, palettized)
272 //      surface = SDL_CreateRGBSurface(SDL_SWSURFACE, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT,
273 //              8, 0, 0, 0, 0);
274         // Create the primary SDL display (32 BPP)
275         surface = SDL_CreateRGBSurface(SDL_SWSURFACE, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32,
276 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
277                 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF
278 #else
279                 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
280 #endif
281                 );
282 /*WriteLog("Video: Created secondary surface with attributes:\n\n");
283 WriteLog("\tWidth, height: %u x %u\n", surface->w, surface->h);
284 WriteLog("\t        Pitch: %u\n", surface->pitch);
285 WriteLog("\t      Palette: %08X\n", surface->format->palette);
286 WriteLog("\t          BPP: %u\n", surface->format->BitsPerPixel);
287 WriteLog("\t      BytesPP: %u\n", surface->format->BytesPerPixel);
288 WriteLog("\t        RMask: %08X\n", surface->format->Rmask);
289 WriteLog("\t        GMask: %08X\n", surface->format->Gmask);
290 WriteLog("\t        BMask: %08X\n", surface->format->Bmask);
291 WriteLog("\t        AMask: %08X\n", surface->format->Amask);
292 WriteLog("\n");//*/
293
294         if (surface == NULL)
295         {
296                 WriteLog("Video: Could not create primary SDL surface: %s\n", SDL_GetError());
297                 return false;
298         }
299
300         // Initialize Williams' palette (RGB coded as: 3 bits red, 3 bits green, 2 bits blue)
301         for(uint32 i=0; i<256; i++)
302 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
303                 palette[i] = (((i & 0x01) * 33 + ((i & 0x02) >> 1) * 71 + ((i & 0x04) >> 2) * 151) << 24)
304                         | ((((i & 0x08) >> 3) * 33 + ((i & 0x10) >> 4) * 71 + ((i & 0x20) >> 5) * 151) << 16)
305                         | ((((i & 0x40) >> 6) * 71 + ((i & 0x80) >> 7) * 151) << 8) | 0xFF;//*/
306 #else
307                 palette[i] = ((i & 0x01) * 33 + ((i & 0x02) >> 1) * 71 + ((i & 0x04) >> 2) * 151)
308                         | ((((i & 0x08) >> 3) * 33 + ((i & 0x10) >> 4) * 71 + ((i & 0x20) >> 5) * 151) << 8)
309                         | ((((i & 0x40) >> 6) * 71 + ((i & 0x80) >> 7) * 151) << 16) | 0xFF000000;//*/
310 #endif
311
312 //      if (vjs.useOpenGL)
313         if (1)
314 //Should make another setting here, for either linear or nearest (instead of just picking one)
315 //And we have! ;-) Not... ;-(
316 //              sdlemu_init_opengl(surface, 1/*method*/, 2/*size*/, 0);//vjs.glFilter/*texture type (linear, nearest)*/);
317                 sdlemu_init_opengl(surface, mainSurface, 1 /*method*/,
318                         0 /*vjs.glFilter /texture type (linear, nearest)*/,
319                         0 /* Automatic bpp selection based upon src */);
320
321         // Initialize Joystick support under SDL
322 /*      if (1)//(vjs.useJoystick)
323         {
324                 if (SDL_NumJoysticks() <= 0)
325                 {
326                         vjs.useJoystick = false;
327                         WriteLog("Video: No joystick(s) or joypad(s) detected on your system. Using keyboard...\n");
328                 }
329                 else
330                 {
331                         if ((joystick = SDL_JoystickOpen(vjs.joyport)) == 0)
332                         {
333                                 vjs.useJoystick = false;
334                                 WriteLog("Video: Unable to open a Joystick on port: %d\n", (int)vjs.joyport);
335                         }
336                         else
337                                 WriteLog("Video: Using: %s\n", SDL_JoystickName(vjs.joyport));
338                 }
339         }*/
340
341         // Set up the backbuffer
342         backbuffer = (uint8 *)malloc(320 * 240 * sizeof(uint8));
343         memset(backbuffer, 0x00, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint8));
344
345         WriteLog("Video: Successfully initialized.\n");
346         return true;
347 }
348
349 #endif
350
351
352
353 //
354 // Render the backbuffer to the primary screen surface
355 //
356 void RenderScreenBuffer(void)
357 {
358 //WriteLog("Video: Blitting a %u x %u surface to the main surface...\n", surface->w, surface->h);
359 //Don't need this crapola--why have a separate buffer just to copy it to THIS
360 //buffer in order to copy it to the main screen? That's what *I* thought!
361 /*      if (SDL_MUSTLOCK(surface))
362                 while (SDL_LockSurface(surface) < 0)
363                         SDL_Delay(10);
364
365         memcpy(surface->pixels, scrBuffer, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint32));
366
367         if (SDL_MUSTLOCK(surface))
368                 SDL_UnlockSurface(surface);//*/
369 #ifdef TEST_ALPHA_BLENDING
370 SDL_Rect dstRect = { 100, 100, 30, 30 };
371 SDL_BlitSurface(someAlphaSurface, NULL, surface, &dstRect);
372 #endif
373
374         if (settings.useOpenGL)
375                 sdlemu_draw_texture(mainSurface, surface, 1/*1=GL_QUADS*/);
376         else
377         {
378                 SDL_BlitSurface(surface, NULL, mainSurface, NULL);
379                 SDL_Flip(mainSurface);
380     }
381 }
382
383 //
384 // Render the backbuffer to the primary screen surface
385 //
386 void RenderScreenBuffer2(void)
387 {
388 #if 0
389 //WriteLog("Video: Blitting a %u x %u surface to the main surface...", surface->w, surface->h);
390         if (SDL_MUSTLOCK(surface))
391                 while (SDL_LockSurface(surface) < 0)
392                         SDL_Delay(10);
393
394 //This *does* ignore the screen's actual pitch... !!! FIX !!!
395         uint32 * screen = (uint32 *)surface->pixels;
396         for(int i=0; i<320*240; i++)
397                 screen[i] = palette[color[scrBuffer[i]]];
398 //WriteLog("[blitted backbuffer]...");
399
400         if (SDL_MUSTLOCK(surface))
401                 SDL_UnlockSurface(surface);
402 #endif
403
404         if (settings.useOpenGL)
405                 sdlemu_draw_texture(mainSurface, surface, 1/*1=GL_QUADS*/);
406         else
407         {
408                 SDL_BlitSurface(surface, NULL, mainSurface, NULL);
409                 SDL_Flip(mainSurface);
410     }
411 //WriteLog("done.\n");
412 }
413
414 /*
415 //
416 // Resize the main SDL screen & backbuffer
417 //
418 void ResizeScreen(uint32 width, uint32 height)
419 {
420         char window_title[256];
421
422         SDL_FreeSurface(surface);
423         surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 16,
424                 0x7C00, 0x03E0, 0x001F, 0);
425
426         if (surface == NULL)
427         {
428                 WriteLog("Video: Could not create primary SDL surface: %s", SDL_GetError());
429                 exit(1);
430         }
431
432         if (vjs.useOpenGL)
433                 // This seems to work well for resizing (i.e., changes in the pixel width)...
434                 sdlemu_resize_texture(surface, mainSurface, vjs.glFilter);
435         else
436         {
437                 mainSurface = SDL_SetVideoMode(width, height, 16, mainSurfaceFlags);
438
439                 if (mainSurface == NULL)
440                 {
441                         WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
442                         exit(1);
443                 }
444         }
445
446         sWriteLog(window_title, "Virtual Jaguar (%i x %i)", (int)width, (int)height);
447         SDL_WM_SetCaption(window_title, window_title);
448
449         // This seems to work well for resizing (i.e., changes in the pixel width)...
450 //      if (vjs.useOpenGL)
451 //              sdlemu_resize_texture(surface, mainSurface);
452 }
453
454 //
455 // Fullscreen <-> window switching
456 //
457 //NOTE: This does *NOT* work with OpenGL rendering! !!! FIX !!!
458 void ToggleFullscreen(void)
459 {
460         vjs.fullscreen = !vjs.fullscreen;
461         mainSurfaceFlags &= ~SDL_FULLSCREEN;
462
463         if (vjs.fullscreen)
464                 mainSurfaceFlags |= SDL_FULLSCREEN;
465
466         mainSurface = SDL_SetVideoMode(tom_width, tom_height, 16, mainSurfaceFlags);
467
468         if (mainSurface == NULL)
469         {
470                 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
471                 exit(1);
472         }
473
474         SDL_WM_SetCaption("Virtual Jaguar", "Virtual Jaguar");
475 }
476 */