2 // VIDEO.CPP: SDL/local hardware specific video routines
\r
4 // by James L. Hammons
\r
6 // JLH = James L. Hammons <jlhamm@acm.org>
\r
9 // --- ---------- ------------------------------------------------------------
\r
10 // JLH 01/04/2006 Added changelog ;-)
\r
11 // JLH 01/20/2006 Cut out unnecessary buffering
\r
17 #include <string.h> // Why??? (for memset, etc... Lazy!) Dunno why, but this just strikes me as wrong...
\r
19 #include "sdlemu_opengl.h"
\r
21 #include "settings.h"
\r
24 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
\r
25 #define MASK_R 0xFF000000
\r
26 #define MASK_G 0x00FF0000
\r
27 #define MASK_B 0x0000FF00
\r
28 #define MASK_A 0x000000FF
\r
30 #define MASK_R 0x000000FF
\r
31 #define MASK_G 0x0000FF00
\r
32 #define MASK_B 0x00FF0000
\r
33 #define MASK_A 0xFF000000
\r
36 //#define TEST_ALPHA_BLENDING
\r
38 // Exported global variables (actually, these are LOCAL global variables, EXPORTED...)
\r
40 SDL_Surface * surface, * mainSurface, * someAlphaSurface;
\r
41 Uint32 mainSurfaceFlags;
\r
42 //uint32 scrBuffer[VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT];
\r
43 uint32 * scrBuffer = NULL;
\r
44 SDL_Joystick * joystick;
\r
47 // Prime SDL and create surfaces
\r
49 bool InitVideo(void)
\r
51 // Set up SDL library
\r
52 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE) < 0)
\r
54 WriteLog("Video: Could not initialize the SDL library: %s\n", SDL_GetError());
\r
58 //Set icon (mainly for Win32 target--though seems to work under KDE as well...!)
\r
59 SDL_Surface * iconSurf = SDL_CreateRGBSurfaceFrom(icon, 32, 32, 32, 128,
\r
60 MASK_R, MASK_G, MASK_B, MASK_A);
\r
61 SDL_WM_SetIcon(iconSurf, NULL);
\r
62 SDL_FreeSurface(iconSurf);
\r
64 // Get proper info about the platform we're running on...
\r
65 const SDL_VideoInfo * info = SDL_GetVideoInfo();
\r
69 WriteLog("Video: SDL is unable to get the video info: %s\n", SDL_GetError());
\r
73 if (settings.useOpenGL)
\r
75 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF | SDL_OPENGL;
\r
76 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
\r
80 mainSurfaceFlags = SDL_DOUBLEBUF;
\r
82 if (info->hw_available)
\r
84 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE;
\r
85 WriteLog("Video: Hardware available...\n");
\r
90 mainSurfaceFlags |= SDL_HWACCEL;
\r
91 WriteLog("Video: Hardware blit available...\n");
\r
95 if (settings.fullscreen)
\r
96 mainSurfaceFlags |= SDL_FULLSCREEN;
\r
98 // Create the primary SDL display (32 BPP)
\r
99 if (!settings.useOpenGL)
\r
100 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
\r
102 // mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH * 2, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
\r
103 // mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
\r
104 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
\r
106 if (mainSurface == NULL)
\r
108 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
\r
112 SDL_WM_SetCaption("Apple 2 SDL", "Apple 2 SDL");
\r
114 // Create the secondary SDL display (32 BPP) that we use directly
\r
115 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32,
\r
116 MASK_R, MASK_G, MASK_B, MASK_A);
\r
117 /*WriteLog("Video: Created secondary surface with attributes:\n\n");
\r
118 WriteLog("\tWidth, height: %u x %u\n", surface->w, surface->h);
\r
119 WriteLog("\t Pitch: %u\n", surface->pitch);
\r
120 WriteLog("\t Palette: %08X\n", surface->format->palette);
\r
121 WriteLog("\t BPP: %u\n", surface->format->BitsPerPixel);
\r
122 WriteLog("\t BytesPP: %u\n", surface->format->BytesPerPixel);
\r
123 WriteLog("\t RMask: %08X\n", surface->format->Rmask);
\r
124 WriteLog("\t GMask: %08X\n", surface->format->Gmask);
\r
125 WriteLog("\t BMask: %08X\n", surface->format->Bmask);
\r
126 WriteLog("\t AMask: %08X\n", surface->format->Amask);
\r
127 WriteLog("\n");//*/
\r
129 if (surface == NULL)
\r
131 WriteLog("Video: Could not create secondary SDL surface: %s\n", SDL_GetError());
\r
135 if (settings.useOpenGL)
\r
136 sdlemu_init_opengl(surface, mainSurface, 1 /*method*/, settings.glFilter /*texture type (linear, nearest)*/,
\r
137 0 /* Automatic bpp selection based upon src */);
\r
139 // Initialize Joystick support under SDL
\r
140 /* if (settings.useJoystick)
\r
142 if (SDL_NumJoysticks() <= 0)
\r
144 settings.useJoystick = false;
\r
145 WriteLog("Video: No joystick(s) or joypad(s) detected on your system. Using keyboard...\n");
\r
149 if ((joystick = SDL_JoystickOpen(settings.joyport)) == 0)
\r
151 settings.useJoystick = false;
\r
152 WriteLog("Video: Unable to open a Joystick on port: %d\n", (int)settings.joyport);
\r
155 WriteLog("Video: Using: %s\n", SDL_JoystickName(settings.joyport));
\r
159 // Set up the scrBuffer
\r
160 scrBuffer = (uint32 *)surface->pixels; // Kludge--And shouldn't have to lock since it's a software surface...
\r
161 //needed? Dunno. Mebbe an SDL function instead?
\r
162 // memset(scrBuffer, 0x00, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint32));
\r
164 #ifdef TEST_ALPHA_BLENDING
\r
165 //Here's some code to test alpha blending...
\r
166 //Well whaddya know, it works. :-)
\r
167 someAlphaSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 30, 30, 32,
\r
168 MASK_R, MASK_G, MASK_B, MASK_A);
\r
170 for(int i=0; i<30; i++)
\r
172 for(int j=0; j<30; j++)
\r
174 uint32 color = (uint32)(((double)(i * j) / (29.0 * 29.0)) * 255.0);
\r
175 color = (color << 24) | 0x00FF00FF;
\r
176 ((uint32 *)someAlphaSurface->pixels)[(j * 30) + i] = color;
\r
182 WriteLog("Video: Successfully initialized.\n");
\r
187 // Free various SDL components
\r
189 void VideoDone(void)
\r
191 if (settings.useOpenGL)
\r
192 sdlemu_close_opengl();
\r
194 SDL_JoystickClose(joystick);
\r
195 SDL_FreeSurface(surface);
\r
196 SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER);
\r
201 // Render the screen buffer to the primary screen surface
\r
203 //void RenderBackbuffer(void)
\r
204 void RenderScreenBuffer(void)
\r
206 //WriteLog("Video: Blitting a %u x %u surface to the main surface...\n", surface->w, surface->h);
\r
207 //Don't need this crapola--why have a separate buffer just to copy it to THIS
\r
208 //buffer in order to copy it to the main screen? That's what *I* thought!
\r
209 /* if (SDL_MUSTLOCK(surface))
\r
210 while (SDL_LockSurface(surface) < 0)
\r
213 memcpy(surface->pixels, scrBuffer, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint32));
\r
215 if (SDL_MUSTLOCK(surface))
\r
216 SDL_UnlockSurface(surface);//*/
\r
217 #ifdef TEST_ALPHA_BLENDING
\r
218 SDL_Rect dstRect = { 100, 100, 30, 30 };
\r
219 SDL_BlitSurface(someAlphaSurface, NULL, surface, &dstRect);
\r
222 if (settings.useOpenGL)
\r
223 sdlemu_draw_texture(mainSurface, surface, 1/*1=GL_QUADS*/);
\r
226 // SDL_Rect rect = { 0, 0, surface->w, surface->h };
\r
227 // SDL_BlitSurface(surface, &rect, mainSurface, &rect);
\r
228 SDL_BlitSurface(surface, NULL, mainSurface, NULL);
\r
229 SDL_Flip(mainSurface);
\r
235 // Resize the main SDL screen & scrBuffer
\r
237 void ResizeScreen(uint32 width, uint32 height)
\r
239 char window_title[256];
\r
241 SDL_FreeSurface(surface);
\r
242 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 16,
\r
243 0x7C00, 0x03E0, 0x001F, 0);
\r
245 if (surface == NULL)
\r
247 WriteLog("Video: Could not create primary SDL surface: %s", SDL_GetError());
\r
251 if (settings.useOpenGL)
\r
252 // This seems to work well for resizing (i.e., changes in the pixel width)...
\r
253 sdlemu_resize_texture(surface, mainSurface, settings.glFilter);
\r
256 mainSurface = SDL_SetVideoMode(width, height, 16, mainSurfaceFlags);
\r
258 if (mainSurface == NULL)
\r
260 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
\r
265 sWriteLog(window_title, "Virtual Jaguar (%i x %i)", (int)width, (int)height);
\r
266 SDL_WM_SetCaption(window_title, window_title);
\r
268 // This seems to work well for resizing (i.e., changes in the pixel width)...
\r
269 // if (settings.useOpenGL)
\r
270 // sdlemu_resize_texture(surface, mainSurface);
\r
275 // Fullscreen <-> window switching
\r
277 //NOTE: This does *NOT* work with OpenGL rendering! !!! FIX !!!
\r
278 void ToggleFullscreen(void)
\r
280 settings.fullscreen = !settings.fullscreen;
\r
281 mainSurfaceFlags &= ~SDL_FULLSCREEN;
\r
283 if (settings.fullscreen)
\r
284 mainSurfaceFlags |= SDL_FULLSCREEN;
\r
286 if (!settings.useOpenGL)
\r
287 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
\r
289 // mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH * 2, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
\r
290 // mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
\r
291 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
\r
292 // mainSurface = SDL_SetVideoMode(tom_width, tom_height, 16, mainSurfaceFlags);
\r
294 if (mainSurface == NULL)
\r
296 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
\r
300 SDL_WM_SetCaption("Apple 2 SDL", "Apple 2 SDL");
\r