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_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,
107 MASK_R, MASK_G, MASK_B, MASK_A);
108 /*WriteLog("Video: Created secondary surface with attributes:\n\n");
109 WriteLog("\tWidth, height: %u x %u\n", surface->w, surface->h);
110 WriteLog("\t Pitch: %u\n", surface->pitch);
111 WriteLog("\t Palette: %08X\n", surface->format->palette);
112 WriteLog("\t BPP: %u\n", surface->format->BitsPerPixel);
113 WriteLog("\t BytesPP: %u\n", surface->format->BytesPerPixel);
114 WriteLog("\t RMask: %08X\n", surface->format->Rmask);
115 WriteLog("\t GMask: %08X\n", surface->format->Gmask);
116 WriteLog("\t BMask: %08X\n", surface->format->Bmask);
117 WriteLog("\t AMask: %08X\n", surface->format->Amask);
122 WriteLog("Video: Could not create secondary SDL surface: %s\n", SDL_GetError());
126 if (settings.useOpenGL)
127 sdlemu_init_opengl(surface, mainSurface, 1 /*method*/,
128 settings.glFilter /*texture type (linear, nearest)*/,
129 0 /* Automatic bpp selection based upon src */);
131 // Initialize Joystick support under SDL
132 /* if (settings.useJoystick)
134 if (SDL_NumJoysticks() <= 0)
136 settings.useJoystick = false;
137 WriteLog("Video: No joystick(s) or joypad(s) detected on your system. Using keyboard...\n");
141 if ((joystick = SDL_JoystickOpen(settings.joyport)) == 0)
143 settings.useJoystick = false;
144 WriteLog("Video: Unable to open a Joystick on port: %d\n", (int)settings.joyport);
147 WriteLog("Video: Using: %s\n", SDL_JoystickName(settings.joyport));
151 // Set up the scrBuffer
152 scrBuffer = (uint32 *)surface->pixels; // Kludge--And shouldn't have to lock since it's a software surface...
153 //needed? Dunno. Mebbe an SDL function instead?
154 // memset(scrBuffer, 0x00, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint32));
156 #ifdef TEST_ALPHA_BLENDING
157 //Here's some code to test alpha blending...
158 //Well whaddya know, it works. :-)
159 someAlphaSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 30, 30, 32,
160 MASK_R, MASK_G, MASK_B, MASK_A);
162 for(int i=0; i<30; i++)
164 for(int j=0; j<30; j++)
166 uint32 color = (uint32)(((double)(i * j) / (29.0 * 29.0)) * 255.0);
167 color = (color << 24) | 0x00FF00FF;
168 ((uint32 *)someAlphaSurface->pixels)[(j * 30) + i] = color;
174 WriteLog("Video: Successfully initialized.\n");
179 // Free various SDL components
183 if (settings.useOpenGL)
184 sdlemu_close_opengl();
186 SDL_JoystickClose(joystick);
187 SDL_FreeSurface(surface);
188 SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER);
198 #include <string.h> // Why??? (for memset, etc... Lazy!) Dunno why, but this just strikes me as wrong...
200 #include "sdlemu_opengl.h"
203 #include "settings.h"
206 // External global variables
208 SDL_Surface * surface, * mainSurface;
209 Uint32 mainSurfaceFlags;
211 SDL_Joystick * joystick;
216 // Prime SDL and create surfaces
220 // Set up SDL library
221 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE) < 0)
223 WriteLog("Video: Could not initialize the SDL library: %s\n", SDL_GetError());
227 // Get proper info about the platform we're running on...
228 const SDL_VideoInfo * info = SDL_GetVideoInfo();
232 WriteLog("Video: SDL is unable to get the video info: %s\n", SDL_GetError());
236 if (1)//(vjs.useOpenGL)
238 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF | SDL_OPENGL;
239 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
243 if (info->hw_available)
245 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF;
246 WriteLog("Video: Hardware available...\n");
251 mainSurfaceFlags |= SDL_HWACCEL;
252 WriteLog("Video: Hardware blit available...\n");
256 // if (vjs.fullscreen)
257 // mainSurfaceFlags |= SDL_FULLSCREEN;
259 if (0)//(!vjs.useOpenGL)
260 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
262 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH * 2, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
264 if (mainSurface == NULL)
266 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
270 SDL_WM_SetCaption("StarGem2", "StarGem2");
272 // Create the primary SDL display (8 BPP, palettized)
273 // surface = SDL_CreateRGBSurface(SDL_SWSURFACE, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT,
275 // Create the primary SDL display (32 BPP)
276 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32,
277 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
278 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF
280 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
283 /*WriteLog("Video: Created secondary surface with attributes:\n\n");
284 WriteLog("\tWidth, height: %u x %u\n", surface->w, surface->h);
285 WriteLog("\t Pitch: %u\n", surface->pitch);
286 WriteLog("\t Palette: %08X\n", surface->format->palette);
287 WriteLog("\t BPP: %u\n", surface->format->BitsPerPixel);
288 WriteLog("\t BytesPP: %u\n", surface->format->BytesPerPixel);
289 WriteLog("\t RMask: %08X\n", surface->format->Rmask);
290 WriteLog("\t GMask: %08X\n", surface->format->Gmask);
291 WriteLog("\t BMask: %08X\n", surface->format->Bmask);
292 WriteLog("\t AMask: %08X\n", surface->format->Amask);
297 WriteLog("Video: Could not create primary SDL surface: %s\n", SDL_GetError());
301 // Initialize Williams' palette (RGB coded as: 3 bits red, 3 bits green, 2 bits blue)
302 for(uint32 i=0; i<256; i++)
303 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
304 palette[i] = (((i & 0x01) * 33 + ((i & 0x02) >> 1) * 71 + ((i & 0x04) >> 2) * 151) << 24)
305 | ((((i & 0x08) >> 3) * 33 + ((i & 0x10) >> 4) * 71 + ((i & 0x20) >> 5) * 151) << 16)
306 | ((((i & 0x40) >> 6) * 71 + ((i & 0x80) >> 7) * 151) << 8) | 0xFF;//*/
308 palette[i] = ((i & 0x01) * 33 + ((i & 0x02) >> 1) * 71 + ((i & 0x04) >> 2) * 151)
309 | ((((i & 0x08) >> 3) * 33 + ((i & 0x10) >> 4) * 71 + ((i & 0x20) >> 5) * 151) << 8)
310 | ((((i & 0x40) >> 6) * 71 + ((i & 0x80) >> 7) * 151) << 16) | 0xFF000000;//*/
313 // if (vjs.useOpenGL)
315 //Should make another setting here, for either linear or nearest (instead of just picking one)
316 //And we have! ;-) Not... ;-(
317 // sdlemu_init_opengl(surface, 1/*method*/, 2/*size*/, 0);//vjs.glFilter/*texture type (linear, nearest)*/);
318 sdlemu_init_opengl(surface, mainSurface, 1 /*method*/,
319 0 /*vjs.glFilter /texture type (linear, nearest)*/,
320 0 /* Automatic bpp selection based upon src */);
322 // Initialize Joystick support under SDL
323 /* if (1)//(vjs.useJoystick)
325 if (SDL_NumJoysticks() <= 0)
327 vjs.useJoystick = false;
328 WriteLog("Video: No joystick(s) or joypad(s) detected on your system. Using keyboard...\n");
332 if ((joystick = SDL_JoystickOpen(vjs.joyport)) == 0)
334 vjs.useJoystick = false;
335 WriteLog("Video: Unable to open a Joystick on port: %d\n", (int)vjs.joyport);
338 WriteLog("Video: Using: %s\n", SDL_JoystickName(vjs.joyport));
342 // Set up the backbuffer
343 backbuffer = (uint8 *)malloc(320 * 240 * sizeof(uint8));
344 memset(backbuffer, 0x00, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint8));
346 WriteLog("Video: Successfully initialized.\n");
355 // Render the backbuffer to the primary screen surface
357 void RenderScreenBuffer(void)
359 //WriteLog("Video: Blitting a %u x %u surface to the main surface...\n", surface->w, surface->h);
360 //Don't need this crapola--why have a separate buffer just to copy it to THIS
361 //buffer in order to copy it to the main screen? That's what *I* thought!
362 /* if (SDL_MUSTLOCK(surface))
363 while (SDL_LockSurface(surface) < 0)
366 memcpy(surface->pixels, scrBuffer, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint32));
368 if (SDL_MUSTLOCK(surface))
369 SDL_UnlockSurface(surface);//*/
370 #ifdef TEST_ALPHA_BLENDING
371 SDL_Rect dstRect = { 100, 100, 30, 30 };
372 SDL_BlitSurface(someAlphaSurface, NULL, surface, &dstRect);
375 if (settings.useOpenGL)
376 sdlemu_draw_texture(mainSurface, surface, 1/*1=GL_QUADS*/);
379 SDL_BlitSurface(surface, NULL, mainSurface, NULL);
380 SDL_Flip(mainSurface);
385 // Render the backbuffer to the primary screen surface
387 void RenderScreenBuffer2(void)
390 //WriteLog("Video: Blitting a %u x %u surface to the main surface...", surface->w, surface->h);
391 if (SDL_MUSTLOCK(surface))
392 while (SDL_LockSurface(surface) < 0)
395 //This *does* ignore the screen's actual pitch... !!! FIX !!!
396 uint32 * screen = (uint32 *)surface->pixels;
397 for(int i=0; i<320*240; i++)
398 screen[i] = palette[color[scrBuffer[i]]];
399 //WriteLog("[blitted backbuffer]...");
401 if (SDL_MUSTLOCK(surface))
402 SDL_UnlockSurface(surface);
405 if (settings.useOpenGL)
406 sdlemu_draw_texture(mainSurface, surface, 1/*1=GL_QUADS*/);
409 SDL_BlitSurface(surface, NULL, mainSurface, NULL);
410 SDL_Flip(mainSurface);
412 //WriteLog("done.\n");
417 // Resize the main SDL screen & backbuffer
419 void ResizeScreen(uint32 width, uint32 height)
421 char window_title[256];
423 SDL_FreeSurface(surface);
424 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 16,
425 0x7C00, 0x03E0, 0x001F, 0);
429 WriteLog("Video: Could not create primary SDL surface: %s", SDL_GetError());
434 // This seems to work well for resizing (i.e., changes in the pixel width)...
435 sdlemu_resize_texture(surface, mainSurface, vjs.glFilter);
438 mainSurface = SDL_SetVideoMode(width, height, 16, mainSurfaceFlags);
440 if (mainSurface == NULL)
442 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
447 sWriteLog(window_title, "Virtual Jaguar (%i x %i)", (int)width, (int)height);
448 SDL_WM_SetCaption(window_title, window_title);
450 // This seems to work well for resizing (i.e., changes in the pixel width)...
451 // if (vjs.useOpenGL)
452 // sdlemu_resize_texture(surface, mainSurface);
456 // Fullscreen <-> window switching
458 //NOTE: This does *NOT* work with OpenGL rendering! !!! FIX !!!
459 void ToggleFullscreen(void)
461 vjs.fullscreen = !vjs.fullscreen;
462 mainSurfaceFlags &= ~SDL_FULLSCREEN;
465 mainSurfaceFlags |= SDL_FULLSCREEN;
467 mainSurface = SDL_SetVideoMode(tom_width, tom_height, 16, mainSurfaceFlags);
469 if (mainSurface == NULL)
471 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
475 SDL_WM_SetCaption("Virtual Jaguar", "Virtual Jaguar");