2 // VIDEO.CPP: SDL/local hardware specific video routines
10 #include <string.h> // Why??? (for memset, etc... Lazy!) Dunno why, but this just strikes me as wrong...
12 #include "sdlemu_opengl.h"
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
23 #define MASK_R 0x000000FF
24 #define MASK_G 0x0000FF00
25 #define MASK_B 0x00FF0000
26 #define MASK_A 0xFF000000
29 //#define TEST_ALPHA_BLENDING
31 // Exported global variables (actually, these are LOCAL global variables, EXPORTED...)
33 SDL_Surface * surface, * mainSurface, * someAlphaSurface;
34 Uint32 mainSurfaceFlags;
35 uint32 * scrBuffer = NULL;
36 SDL_Joystick * joystick;
39 // Prime SDL and create surfaces
44 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE) < 0)
46 WriteLog("Video: Could not initialize the SDL library: %s\n", SDL_GetError());
50 // Get proper info about the platform we're running on...
51 const SDL_VideoInfo * info = SDL_GetVideoInfo();
55 WriteLog("Video: SDL is unable to get the video info: %s\n", SDL_GetError());
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"));
62 if (settings.useOpenGL)
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);
73 mainSurfaceFlags = SDL_DOUBLEBUF;
75 if (info->hw_available)
76 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE;
79 mainSurfaceFlags |= SDL_HWACCEL;
82 if (settings.fullscreen)
83 mainSurfaceFlags |= SDL_FULLSCREEN;
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);
89 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
91 if (mainSurface == NULL)
93 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
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);
103 SDL_WM_SetCaption("StarGem2", "StarGem2");
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);
121 WriteLog("Video: Could not create secondary SDL surface: %s\n", SDL_GetError());
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 */);
130 // Initialize Joystick support under SDL
131 /* if (settings.useJoystick)
133 if (SDL_NumJoysticks() <= 0)
135 settings.useJoystick = false;
136 WriteLog("Video: No joystick(s) or joypad(s) detected on your system. Using keyboard...\n");
140 if ((joystick = SDL_JoystickOpen(settings.joyport)) == 0)
142 settings.useJoystick = false;
143 WriteLog("Video: Unable to open a Joystick on port: %d\n", (int)settings.joyport);
146 WriteLog("Video: Using: %s\n", SDL_JoystickName(settings.joyport));
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));
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);
161 for(int i=0; i<30; i++)
163 for(int j=0; j<30; j++)
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;
173 WriteLog("Video: Successfully initialized.\n");
178 // Free various SDL components
182 if (settings.useOpenGL)
183 sdlemu_close_opengl();
185 // SDL_JoystickClose(joystick);
186 SDL_FreeSurface(surface);
187 // SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER);
197 #include <string.h> // Why??? (for memset, etc... Lazy!) Dunno why, but this just strikes me as wrong...
199 #include "sdlemu_opengl.h"
202 #include "settings.h"
205 // External global variables
207 SDL_Surface * surface, * mainSurface;
208 Uint32 mainSurfaceFlags;
210 SDL_Joystick * joystick;
215 // Prime SDL and create surfaces
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)
222 WriteLog("Video: Could not initialize the SDL library: %s\n", SDL_GetError());
226 // Get proper info about the platform we're running on...
227 const SDL_VideoInfo * info = SDL_GetVideoInfo();
231 WriteLog("Video: SDL is unable to get the video info: %s\n", SDL_GetError());
235 if (1)//(vjs.useOpenGL)
237 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF | SDL_OPENGL;
238 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
242 if (info->hw_available)
244 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF;
245 WriteLog("Video: Hardware available...\n");
250 mainSurfaceFlags |= SDL_HWACCEL;
251 WriteLog("Video: Hardware blit available...\n");
255 // if (vjs.fullscreen)
256 // mainSurfaceFlags |= SDL_FULLSCREEN;
258 if (0)//(!vjs.useOpenGL)
259 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
261 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH * 2, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
263 if (mainSurface == NULL)
265 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
269 SDL_WM_SetCaption("StarGem2", "StarGem2");
271 // Create the primary SDL display (8 BPP, palettized)
272 // surface = SDL_CreateRGBSurface(SDL_SWSURFACE, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT,
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
279 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
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);
296 WriteLog("Video: Could not create primary SDL surface: %s\n", SDL_GetError());
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;//*/
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;//*/
312 // if (vjs.useOpenGL)
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 */);
321 // Initialize Joystick support under SDL
322 /* if (1)//(vjs.useJoystick)
324 if (SDL_NumJoysticks() <= 0)
326 vjs.useJoystick = false;
327 WriteLog("Video: No joystick(s) or joypad(s) detected on your system. Using keyboard...\n");
331 if ((joystick = SDL_JoystickOpen(vjs.joyport)) == 0)
333 vjs.useJoystick = false;
334 WriteLog("Video: Unable to open a Joystick on port: %d\n", (int)vjs.joyport);
337 WriteLog("Video: Using: %s\n", SDL_JoystickName(vjs.joyport));
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));
345 WriteLog("Video: Successfully initialized.\n");
354 // Render the backbuffer to the primary screen surface
356 void RenderScreenBuffer(void)
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)
365 memcpy(surface->pixels, scrBuffer, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint32));
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);
374 if (settings.useOpenGL)
375 sdlemu_draw_texture(mainSurface, surface, 1/*1=GL_QUADS*/);
378 SDL_BlitSurface(surface, NULL, mainSurface, NULL);
379 SDL_Flip(mainSurface);
384 // Render the backbuffer to the primary screen surface
386 void RenderScreenBuffer2(void)
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)
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]...");
400 if (SDL_MUSTLOCK(surface))
401 SDL_UnlockSurface(surface);
404 if (settings.useOpenGL)
405 sdlemu_draw_texture(mainSurface, surface, 1/*1=GL_QUADS*/);
408 SDL_BlitSurface(surface, NULL, mainSurface, NULL);
409 SDL_Flip(mainSurface);
411 //WriteLog("done.\n");
416 // Resize the main SDL screen & backbuffer
418 void ResizeScreen(uint32 width, uint32 height)
420 char window_title[256];
422 SDL_FreeSurface(surface);
423 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 16,
424 0x7C00, 0x03E0, 0x001F, 0);
428 WriteLog("Video: Could not create primary SDL surface: %s", SDL_GetError());
433 // This seems to work well for resizing (i.e., changes in the pixel width)...
434 sdlemu_resize_texture(surface, mainSurface, vjs.glFilter);
437 mainSurface = SDL_SetVideoMode(width, height, 16, mainSurfaceFlags);
439 if (mainSurface == NULL)
441 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
446 sWriteLog(window_title, "Virtual Jaguar (%i x %i)", (int)width, (int)height);
447 SDL_WM_SetCaption(window_title, window_title);
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);
455 // Fullscreen <-> window switching
457 //NOTE: This does *NOT* work with OpenGL rendering! !!! FIX !!!
458 void ToggleFullscreen(void)
460 vjs.fullscreen = !vjs.fullscreen;
461 mainSurfaceFlags &= ~SDL_FULLSCREEN;
464 mainSurfaceFlags |= SDL_FULLSCREEN;
466 mainSurface = SDL_SetVideoMode(tom_width, tom_height, 16, mainSurfaceFlags);
468 if (mainSurface == NULL)
470 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
474 SDL_WM_SetCaption("Virtual Jaguar", "Virtual Jaguar");