]> Shamusworld >> Repos - apple2/blob - src/video.cpp
Moved stuff into trunk (part 2)...
[apple2] / src / video.cpp
1 //\r
2 // VIDEO.CPP: SDL/local hardware specific video routines\r
3 //\r
4 // by James L. Hammons\r
5 //\r
6 // JLH = James L. Hammons <jlhamm@acm.org>\r
7 //\r
8 // WHO  WHEN        WHAT\r
9 // ---  ----------  ------------------------------------------------------------\r
10 // JLH  01/04/2006  Added changelog ;-)\r
11 // JLH  01/20/2006  Cut out unnecessary buffering\r
12 //\r
13 \r
14 #include "video.h"\r
15 \r
16 //#include <SDL.h>\r
17 #include <string.h>     // Why??? (for memset, etc... Lazy!) Dunno why, but this just strikes me as wrong...\r
18 #include <malloc.h>\r
19 #include "sdlemu_opengl.h"\r
20 #include "log.h"\r
21 #include "settings.h"\r
22 #include "icon.h"\r
23 \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
29 #else\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
34 #endif\r
35 \r
36 //#define TEST_ALPHA_BLENDING\r
37 \r
38 // Exported global variables (actually, these are LOCAL global variables, EXPORTED...)\r
39 \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
45 \r
46 //\r
47 // Prime SDL and create surfaces\r
48 //\r
49 bool InitVideo(void)\r
50 {\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
53         {\r
54                 WriteLog("Video: Could not initialize the SDL library: %s\n", SDL_GetError());\r
55                 return false;\r
56         }\r
57 \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
63 \r
64         // Get proper info about the platform we're running on...\r
65         const SDL_VideoInfo * info = SDL_GetVideoInfo();\r
66 \r
67         if (!info)\r
68         {\r
69                 WriteLog("Video: SDL is unable to get the video info: %s\n", SDL_GetError());\r
70                 return false;\r
71         }\r
72 \r
73         if (settings.useOpenGL)\r
74         {\r
75                 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF | SDL_OPENGL;\r
76                 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);\r
77         }\r
78         else\r
79         {\r
80                 mainSurfaceFlags = SDL_DOUBLEBUF;\r
81 \r
82                 if (info->hw_available)\r
83                 {\r
84                         mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE;\r
85                         WriteLog("Video: Hardware available...\n");\r
86                 }\r
87 \r
88                 if (info->blit_hw)\r
89                 {\r
90                         mainSurfaceFlags |= SDL_HWACCEL;\r
91                         WriteLog("Video: Hardware blit available...\n");\r
92                 }\r
93         }\r
94 \r
95         if (settings.fullscreen)\r
96                 mainSurfaceFlags |= SDL_FULLSCREEN;\r
97 \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
101         else\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
105 \r
106         if (mainSurface == NULL)\r
107         {\r
108                 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());\r
109                 return false;\r
110         }\r
111 \r
112         SDL_WM_SetCaption("Apple 2 SDL", "Apple 2 SDL");\r
113 \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
128 \r
129         if (surface == NULL)\r
130         {\r
131                 WriteLog("Video: Could not create secondary SDL surface: %s\n", SDL_GetError());\r
132                 return false;\r
133         }\r
134 \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
138 \r
139         // Initialize Joystick support under SDL\r
140 /*      if (settings.useJoystick)\r
141         {\r
142                 if (SDL_NumJoysticks() <= 0)\r
143                 {\r
144                         settings.useJoystick = false;\r
145                         WriteLog("Video: No joystick(s) or joypad(s) detected on your system. Using keyboard...\n");\r
146                 }\r
147                 else\r
148                 {\r
149                         if ((joystick = SDL_JoystickOpen(settings.joyport)) == 0)\r
150                         {\r
151                                 settings.useJoystick = false;\r
152                                 WriteLog("Video: Unable to open a Joystick on port: %d\n", (int)settings.joyport);\r
153                         }\r
154                         else\r
155                                 WriteLog("Video: Using: %s\n", SDL_JoystickName(settings.joyport));\r
156                 }\r
157         }//*/\r
158 \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
163 \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
169 \r
170         for(int i=0; i<30; i++)\r
171         {\r
172                 for(int j=0; j<30; j++)\r
173                 {\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
177                 }\r
178         }\r
179 //End test code\r
180 #endif\r
181 \r
182         WriteLog("Video: Successfully initialized.\n");\r
183         return true;\r
184 }\r
185 \r
186 //\r
187 // Free various SDL components\r
188 //\r
189 void VideoDone(void)\r
190 {\r
191         if (settings.useOpenGL)\r
192                 sdlemu_close_opengl();\r
193 \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
197         SDL_Quit();\r
198 }\r
199 \r
200 //\r
201 // Render the screen buffer to the primary screen surface\r
202 //\r
203 //void RenderBackbuffer(void)\r
204 void RenderScreenBuffer(void)\r
205 {\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
211                         SDL_Delay(10);\r
212 \r
213         memcpy(surface->pixels, scrBuffer, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint32));\r
214 \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
220 #endif\r
221 \r
222         if (settings.useOpenGL)\r
223                 sdlemu_draw_texture(mainSurface, surface, 1/*1=GL_QUADS*/);\r
224         else\r
225         {\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
230     }\r
231 }\r
232 \r
233 /*\r
234 //\r
235 // Resize the main SDL screen & scrBuffer\r
236 //\r
237 void ResizeScreen(uint32 width, uint32 height)\r
238 {\r
239         char window_title[256];\r
240 \r
241         SDL_FreeSurface(surface);\r
242         surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 16,\r
243                 0x7C00, 0x03E0, 0x001F, 0);\r
244 \r
245         if (surface == NULL)\r
246         {\r
247                 WriteLog("Video: Could not create primary SDL surface: %s", SDL_GetError());\r
248                 exit(1);\r
249         }\r
250 \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
254         else\r
255         {\r
256                 mainSurface = SDL_SetVideoMode(width, height, 16, mainSurfaceFlags);\r
257 \r
258                 if (mainSurface == NULL)\r
259                 {\r
260                         WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());\r
261                         exit(1);\r
262                 }\r
263         }\r
264 \r
265         sWriteLog(window_title, "Virtual Jaguar (%i x %i)", (int)width, (int)height);\r
266         SDL_WM_SetCaption(window_title, window_title);\r
267 \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
271 }*/\r
272 \r
273 /*\r
274 //\r
275 // Fullscreen <-> window switching\r
276 //\r
277 //NOTE: This does *NOT* work with OpenGL rendering! !!! FIX !!!\r
278 void ToggleFullscreen(void)\r
279 {\r
280         settings.fullscreen = !settings.fullscreen;\r
281         mainSurfaceFlags &= ~SDL_FULLSCREEN;\r
282 \r
283         if (settings.fullscreen)\r
284                 mainSurfaceFlags |= SDL_FULLSCREEN;\r
285 \r
286         if (!settings.useOpenGL)\r
287                 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);\r
288         else\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
293 \r
294         if (mainSurface == NULL)\r
295         {\r
296                 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());\r
297                 exit(1);\r
298         }\r
299 \r
300         SDL_WM_SetCaption("Apple 2 SDL", "Apple 2 SDL");\r
301 }\r
302 //*/\r