2 // VIDEO.CPP: SDL/local hardware specific video routines
6 // JLH = James L. Hammons <jlhamm@acm.org>
9 // --- ---------- ------------------------------------------------------------
10 // JLH 01/04/2006 Added changelog ;-)
11 // JLH 01/20/2006 Cut out unnecessary buffering
17 #include <string.h> // Why??? (for memset, etc... Lazy!) Dunno why, but this just strikes me as wrong...
19 #include "sdlemu_opengl.h"
24 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
25 #define MASK_R 0xFF000000
26 #define MASK_G 0x00FF0000
27 #define MASK_B 0x0000FF00
28 #define MASK_A 0x000000FF
30 #define MASK_R 0x000000FF
31 #define MASK_G 0x0000FF00
32 #define MASK_B 0x00FF0000
33 #define MASK_A 0xFF000000
36 //#define TEST_ALPHA_BLENDING
38 // Exported global variables (actually, these are LOCAL global variables, EXPORTED...)
40 SDL_Surface * surface, * mainSurface, * someAlphaSurface;
41 Uint32 mainSurfaceFlags;
42 //uint32 scrBuffer[VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT];
43 uint32 * scrBuffer = NULL, * mainScrBuffer = NULL;
44 SDL_Joystick * joystick;
47 // Prime SDL and create surfaces
52 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE | SDL_INIT_EVENTTHREAD) < 0)
54 WriteLog("Video: Could not initialize the SDL library: %s\n", SDL_GetError());
58 //Set icon (mainly for Win32 target--though seems to work under KDE as well...!)
59 SDL_Surface * iconSurf = SDL_CreateRGBSurfaceFrom(icon, 32, 32, 32, 128,
60 MASK_R, MASK_G, MASK_B, MASK_A);
61 SDL_WM_SetIcon(iconSurf, NULL);
62 SDL_FreeSurface(iconSurf);
64 // Get proper info about the platform we're running on...
65 const SDL_VideoInfo * info = SDL_GetVideoInfo();
69 WriteLog("Video: SDL is unable to get the video info: %s\n", SDL_GetError());
73 if (settings.useOpenGL)
75 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF | SDL_OPENGL;
76 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
80 mainSurfaceFlags = SDL_DOUBLEBUF;
82 if (info->hw_available)
84 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE;
85 WriteLog("Video: Hardware available...\n");
90 mainSurfaceFlags |= SDL_HWACCEL;
91 WriteLog("Video: Hardware blit available...\n");
95 if (settings.fullscreen)
96 mainSurfaceFlags |= SDL_FULLSCREEN;
98 // Create the primary SDL display (32 BPP)
99 if (!settings.useOpenGL)
100 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
102 // mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH * 2, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
103 // mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
104 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
106 if (mainSurface == NULL)
108 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
112 SDL_WM_SetCaption("Apple 2 SDL", "Apple 2 SDL");
114 // Create the secondary SDL display (32 BPP) that we use directly
115 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32,
116 MASK_R, MASK_G, MASK_B, MASK_A);
118 WriteLog("Video: Created secondary surface with attributes:\n\n");
119 WriteLog("\tWidth, height: %u x %u\n", surface->w, surface->h);
120 WriteLog("\t Pitch: %u\n", surface->pitch);
121 WriteLog("\t Palette: %08X\n", surface->format->palette);
122 WriteLog("\t BPP: %u\n", surface->format->BitsPerPixel);
123 WriteLog("\t BytesPP: %u\n", surface->format->BytesPerPixel);
124 WriteLog("\t RMask: %08X\n", surface->format->Rmask);
125 WriteLog("\t GMask: %08X\n", surface->format->Gmask);
126 WriteLog("\t BMask: %08X\n", surface->format->Bmask);
127 WriteLog("\t AMask: %08X\n", surface->format->Amask);
133 WriteLog("Video: Could not create secondary SDL surface: %s\n", SDL_GetError());
137 if (settings.useOpenGL)
138 sdlemu_init_opengl(surface, mainSurface, 1 /*method*/, settings.glFilter /*texture type (linear, nearest)*/,
139 0 /* Automatic bpp selection based upon src */);
141 // Initialize Joystick support under SDL
142 /* if (settings.useJoystick)
144 if (SDL_NumJoysticks() <= 0)
146 settings.useJoystick = false;
147 WriteLog("Video: No joystick(s) or joypad(s) detected on your system. Using keyboard...\n");
151 if ((joystick = SDL_JoystickOpen(settings.joyport)) == 0)
153 settings.useJoystick = false;
154 WriteLog("Video: Unable to open a Joystick on port: %d\n", (int)settings.joyport);
157 WriteLog("Video: Using: %s\n", SDL_JoystickName(settings.joyport));
161 // Set up the scrBuffer
162 scrBuffer = (uint32 *)surface->pixels; // Kludge--And shouldn't have to lock since it's a software surface...
163 //needed? Dunno. Mebbe an SDL function instead?
164 // memset(scrBuffer, 0x00, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint32));
165 // Set up the mainScrBuffer
166 mainScrBuffer = (uint32 *)mainSurface->pixels; // May need to lock...
168 #ifdef TEST_ALPHA_BLENDING
169 //Here's some code to test alpha blending...
170 //Well whaddya know, it works. :-)
171 someAlphaSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 30, 30, 32,
172 MASK_R, MASK_G, MASK_B, MASK_A);
174 for(int i=0; i<30; i++)
176 for(int j=0; j<30; j++)
178 uint32 color = (uint32)(((double)(i * j) / (29.0 * 29.0)) * 255.0);
179 color = (color << 24) | 0x00FF00FF;
180 ((uint32 *)someAlphaSurface->pixels)[(j * 30) + i] = color;
186 WriteLog("Video: Successfully initialized.\n");
191 // Free various SDL components
195 WriteLog("Video: Shutting down OpenGL...\n");
196 if (settings.useOpenGL)
197 sdlemu_close_opengl();
199 // WriteLog("Video: Shutting down joystick....\n");
200 // SDL_JoystickClose(joystick);
201 WriteLog("Video: Freeing 'surface'...\n");
202 SDL_FreeSurface(surface);
203 #warning "The problem is here: Doing the SDL_Quit function causes a double free. !!! FIX !!!"
204 #warning "Some googling suggests that it may be the thread component causing the trouble."
206 *** glibc detected *** ./apple2: double free or corruption (!prev): 0x08239480 ***
207 ======= Backtrace: =========
208 /lib/libc.so.6[0xb7c96572]
209 /lib/libc.so.6[0xb7c97cc3]
210 /lib/libc.so.6(cfree+0x6d)[0xb7c9afed]
211 /usr/lib/dri/radeon_dri.so(_mesa_free+0x1d)[0xb6edefbd]
212 /usr/lib/dri/radeon_dri.so(_mesa_delete_texture_image+0x41)[0xb6efc6b1]
213 /usr/lib/dri/radeon_dri.so(_mesa_delete_texture_object+0x75)[0xb6f032d5]
214 /usr/lib/dri/radeon_dri.so[0xb6e898fd]
215 /usr/lib/dri/radeon_dri.so[0xb6eab379]
216 /usr/lib/dri/radeon_dri.so(_mesa_HashDeleteAll+0x66)[0xb6ecb236]
217 /usr/lib/dri/radeon_dri.so[0xb6eabb76]
218 /usr/lib/dri/radeon_dri.so(_mesa_free_context_data+0x1d1)[0xb6eac8e1]
219 /usr/lib/dri/radeon_dri.so(_mesa_destroy_context+0x26)[0xb6eac976]
220 /usr/lib/dri/radeon_dri.so(radeonDestroyContext+0x13b)[0xb6e7b97b]
221 /usr/lib/dri/radeon_dri.so[0xb6e779c7]
222 //usr//lib/opengl/xorg-x11/lib/libGL.so.1[0xb7dc3e0c]
223 //usr//lib/opengl/xorg-x11/lib/libGL.so.1[0xb7d9ec75]
224 /usr/lib/libSDL-1.2.so.0[0xb7f488d2]
225 /usr/lib/libSDL-1.2.so.0[0xb7f4cb67]
226 /usr/lib/libSDL-1.2.so.0[0xb7f4cda7]
227 /usr/lib/libSDL-1.2.so.0(SDL_VideoQuit+0x4e)[0xb7f3af6e]
228 /usr/lib/libSDL-1.2.so.0(SDL_QuitSubSystem+0x5b)[0xb7f0e5cb]
229 /usr/lib/libSDL-1.2.so.0(SDL_Quit+0x1e)[0xb7f0e66e]
232 /lib/libc.so.6(__libc_start_main+0xe1)[0xb7c3da51]
235 // WriteLog("Video: Shutting down SDL subsystems...\n");
236 // SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_EVENTTHREAD);
237 WriteLog("Video: Shutting down SDL...\n");
239 WriteLog("Video: Done.\n");
243 // Render the screen buffer to the primary screen surface
245 //void RenderBackbuffer(void)
246 void RenderScreenBuffer(void)
248 //WriteLog("Video: Blitting a %u x %u surface to the main surface...\n", surface->w, surface->h);
249 //Don't need this crapola--why have a separate buffer just to copy it to THIS
250 //buffer in order to copy it to the main screen? That's what *I* thought!
251 /* if (SDL_MUSTLOCK(surface))
252 while (SDL_LockSurface(surface) < 0)
255 memcpy(surface->pixels, scrBuffer, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint32));
257 if (SDL_MUSTLOCK(surface))
258 SDL_UnlockSurface(surface);//*/
259 #ifdef TEST_ALPHA_BLENDING
260 SDL_Rect dstRect = { 100, 100, 30, 30 };
261 SDL_BlitSurface(someAlphaSurface, NULL, surface, &dstRect);
264 if (settings.useOpenGL)
265 sdlemu_draw_texture(mainSurface, surface, 1/*1=GL_QUADS*/);
268 // SDL_Rect rect = { 0, 0, surface->w, surface->h };
269 // SDL_BlitSurface(surface, &rect, mainSurface, &rect);
270 SDL_BlitSurface(surface, NULL, mainSurface, NULL);
271 SDL_Flip(mainSurface);
275 // Is this even necessary? (Could call SDL_Flip directly...)
276 void FlipMainScreen(void)
278 #ifdef TEST_ALPHA_BLENDING
279 SDL_Rect dstRect = { 100, 100, 30, 30 };
280 SDL_BlitSurface(someAlphaSurface, NULL, mainSurface, &dstRect);
283 if (settings.useOpenGL)
284 sdlemu_draw_texture(mainSurface, surface, 1/*1=GL_QUADS*/);
286 SDL_Flip(mainSurface);
291 // Resize the main SDL screen & scrBuffer
293 void ResizeScreen(uint32 width, uint32 height)
295 char window_title[256];
297 SDL_FreeSurface(surface);
298 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 16,
299 0x7C00, 0x03E0, 0x001F, 0);
303 WriteLog("Video: Could not create primary SDL surface: %s", SDL_GetError());
307 if (settings.useOpenGL)
308 // This seems to work well for resizing (i.e., changes in the pixel width)...
309 sdlemu_resize_texture(surface, mainSurface, settings.glFilter);
312 mainSurface = SDL_SetVideoMode(width, height, 16, mainSurfaceFlags);
314 if (mainSurface == NULL)
316 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
321 sWriteLog(window_title, "Virtual Jaguar (%i x %i)", (int)width, (int)height);
322 SDL_WM_SetCaption(window_title, window_title);
324 // This seems to work well for resizing (i.e., changes in the pixel width)...
325 // if (settings.useOpenGL)
326 // sdlemu_resize_texture(surface, mainSurface);
331 // Fullscreen <-> window switching
333 //NOTE: This does *NOT* work with OpenGL rendering! !!! FIX !!!
334 void ToggleFullscreen(void)
336 settings.fullscreen = !settings.fullscreen;
337 mainSurfaceFlags &= ~SDL_FULLSCREEN;
339 if (settings.fullscreen)
340 mainSurfaceFlags |= SDL_FULLSCREEN;
342 if (!settings.useOpenGL)
343 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
345 // mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH * 2, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
346 // mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
347 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
348 // mainSurface = SDL_SetVideoMode(tom_width, tom_height, 16, mainSurfaceFlags);
350 if (mainSurface == NULL)
352 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
356 SDL_WM_SetCaption("Apple 2 SDL", "Apple 2 SDL");