view src/win32/GDIDisplay.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line source
1 #include "stdafx.h"
2 #include <cstdio>
4 #include "resource.h"
5 #include "MainWnd.h"
6 #include "Reg.h"
7 #include "VBA.h"
9 #include "../gba/GBAGlobals.h"
10 #include "../gb/gbGlobals.h"
11 #include "../common/Text.h"
12 #include "../version.h"
14 extern u32 RGB_LOW_BITS_MASK;
15 extern int systemSpeed;
16 extern void winlog(const char *, ...);
17 extern int Init_2xSaI(u32);
19 class GDIDisplay : public IDisplay
20 {
21 private:
22 u8 *filterData;
23 u8 info[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)];
24 public:
25 GDIDisplay();
26 virtual ~GDIDisplay();
28 virtual bool initialize();
29 virtual void cleanup();
30 virtual void render();
31 virtual void checkFullScreen();
32 virtual void renderMenu();
33 virtual void clear();
34 virtual DISPLAY_TYPE getType() { return GDI; };
35 virtual void setOption(const char *, int) {}
36 virtual int selectFullScreenMode(GUID * *);
37 };
39 static int calculateShift(u32 mask)
40 {
41 int m = 0;
43 while (mask)
44 {
45 m++;
46 mask >>= 1;
47 }
49 return m-5;
50 }
52 GDIDisplay::GDIDisplay()
53 {
54 filterData = (u8 *)malloc(4*16*256*256); // sufficient for 4x filters @ 32bit color depth
55 }
57 GDIDisplay::~GDIDisplay()
58 {
59 cleanup();
60 }
62 void GDIDisplay::cleanup()
63 {
64 if (filterData)
65 {
66 free(filterData);
67 filterData = NULL;
68 }
69 }
71 bool GDIDisplay::initialize()
72 {
73 CWnd *pWnd = theApp.m_pMainWnd;
75 theApp.mode320Available = false;
76 theApp.mode640Available = false;
77 theApp.mode800Available = false;
79 HDC dc = GetDC(NULL);
80 HBITMAP hbm = CreateCompatibleBitmap(dc, 1, 1);
81 BITMAPINFO *bi = (BITMAPINFO *)info;
82 ZeroMemory(bi, sizeof(info));
83 bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
84 GetDIBits(dc, hbm, 0, 1, NULL, (LPBITMAPINFO)info, DIB_RGB_COLORS);
85 GetDIBits(dc, hbm, 0, 1, NULL, (LPBITMAPINFO)info, DIB_RGB_COLORS);
86 DeleteObject(hbm);
87 ReleaseDC(NULL, dc);
89 if (bi->bmiHeader.biCompression == BI_BITFIELDS)
90 {
91 systemColorDepth = bi->bmiHeader.biBitCount;
92 if (systemColorDepth == 15)
93 systemColorDepth = 16;
94 systemRedShift = calculateShift(*((DWORD *)&bi->bmiColors[0]));
95 systemGreenShift = calculateShift(*((DWORD *)&bi->bmiColors[1]));
96 systemBlueShift = calculateShift(*((DWORD *)&bi->bmiColors[2]));
97 if (systemColorDepth == 16)
98 {
99 if (systemGreenShift == 6)
100 {
101 Init_2xSaI(565);
102 RGB_LOW_BITS_MASK = 0x821;
103 }
104 else
105 {
106 Init_2xSaI(555);
107 RGB_LOW_BITS_MASK = 0x421;
108 }
109 }
110 else if (systemColorDepth == 32)
111 Init_2xSaI(32);
112 }
113 else
114 {
115 systemColorDepth = 32;
116 systemRedShift = 19;
117 systemGreenShift = 11;
118 systemBlueShift = 3;
120 Init_2xSaI(32);
121 }
122 theApp.fsColorDepth = systemColorDepth;
123 if (systemColorDepth == 24)
124 theApp.filterFunction = NULL;
125 #ifdef MMX
126 if (!theApp.disableMMX)
127 cpu_mmx = theApp.detectMMX();
128 else
129 cpu_mmx = 0;
130 #endif
132 switch (systemColorDepth)
133 {
134 case 16:
135 {
136 for (int i = 0; i < 0x10000; i++)
137 {
138 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
139 (((i & 0x3e0) >> 5) << systemGreenShift) |
140 (((i & 0x7c00) >> 10) << systemBlueShift);
141 }
142 break;
143 }
144 case 24:
145 case 32:
146 {
147 for (int i = 0; i < 0x10000; i++)
148 {
149 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
150 (((i & 0x3e0) >> 5) << systemGreenShift) |
151 (((i & 0x7c00) >> 10) << systemBlueShift);
152 }
153 break;
154 }
155 }
156 theApp.updateFilter();
157 theApp.updateIFB();
159 pWnd->DragAcceptFiles(TRUE);
161 return TRUE;
162 }
164 void GDIDisplay::clear()
165 {}
167 void GDIDisplay::renderMenu()
168 {
169 checkFullScreen();
170 theApp.m_pMainWnd->DrawMenuBar();
171 }
173 void GDIDisplay::checkFullScreen()
174 {}
176 void GDIDisplay::render()
177 {
178 void (*filterFunction)(u8 *, u32, u8 *, u8 *, u32, int, int) = theApp.filterFunction;
179 int filterWidth = theApp.filterWidth, filterHeight = theApp.filterHeight;
180 /*
181 if(textMethod == 1)
182 {
183 int copyX = 240, copyY = 160;
184 if(systemCartridgeType == 1)
185 if(gbBorderOn) copyX = 256, copyY = 224;
186 else copyX = 160, copyY = 144;
188 extern void Simple1x(u8*,u32,u8*,u8*,u32,int,int);
189 filterFunction = Simple1x;
190 filterWidth = copyX*2;
191 filterHeight = copyY*2;
192 }
193 */
194 BITMAPINFO *bi = (BITMAPINFO *)info;
195 bi->bmiHeader.biWidth = filterWidth+1;
196 bi->bmiHeader.biHeight = -filterHeight;
198 int pitch = filterWidth * 2 + 4;
199 if (systemColorDepth == 32)
200 pitch = filterWidth * 4 + 4;
201 // FIXME: is the 24bit color depth still being used nowadays?
202 else if (systemColorDepth == 24)
203 pitch = filterWidth * 3;
205 // FIXME: is this working if systemColorDepth == 24?
206 int filterPitch = theApp.rect.right*2;
207 if (systemColorDepth == 32)
208 filterPitch = theApp.rect.right*4;
209 else if (systemColorDepth == 24)
210 filterPitch = theApp.rect.right*3;
212 /*
213 // HACK: see below
214 if (textMethod == 1 && !filterFunction)
215 {
216 textMethod = 0; // must not be after systemMessage!
217 systemMessage(
218 0,
219 "The \"On Game\" text display mode does not work with this combination of renderers and filters.\nThe display mode is automatically being changed to \"In Game\" instead,\nbut this may cause message text to go into AVI recordings and screenshots.\nThis can be reconfigured by choosing \"Options->Video->Text Display Options...\"");
220 }
221 */
223 if (filterFunction)
224 {
225 bi->bmiHeader.biWidth = theApp.rect.right;
226 bi->bmiHeader.biHeight = -theApp.rect.bottom;
228 (*filterFunction)(pix + pitch,
229 pitch,
230 (u8 *)theApp.delta,
231 (u8 *)filterData,
232 filterPitch,
233 filterWidth,
234 filterHeight);
235 }
237 if (theApp.showSpeed && theApp.videoOption > VIDEO_4X)
238 {
239 char buffer[30];
240 if (theApp.showSpeed == 1)
241 sprintf(buffer, "%3d%%", systemSpeed);
242 else
243 sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
244 systemFrameSkip,
245 theApp.showRenderedFrames);
247 if (filterFunction)
248 {
249 if (theApp.showSpeedTransparent)
250 drawTextTransp((u8 *)filterData,
251 filterPitch,
252 theApp.rect.left+10,
253 theApp.rect.bottom-10,
254 buffer);
255 else
256 drawText((u8 *)filterData,
257 filterPitch,
258 theApp.rect.left+10,
259 theApp.rect.bottom-10,
260 buffer);
261 }
262 else
263 {
264 if (theApp.showSpeedTransparent)
265 drawTextTransp((u8 *)pix,
266 pitch,
267 theApp.rect.left+10,
268 theApp.rect.bottom-10,
269 buffer);
270 else
271 drawText((u8 *)pix,
272 pitch,
273 theApp.rect.left+10,
274 theApp.rect.bottom-10,
275 buffer);
276 }
277 }
279 if (textMethod == 1 && filterFunction)
280 {
281 DrawTextMessages((u8 *)filterData, filterPitch, theApp.rect.left, theApp.rect.bottom);
282 }
284 POINT p;
285 p.x = theApp.dest.left;
286 p.y = theApp.dest.top;
287 CWnd *pWnd = theApp.m_pMainWnd;
288 pWnd->ScreenToClient(&p);
289 POINT p2;
290 p2.x = theApp.dest.right;
291 p2.y = theApp.dest.bottom;
292 pWnd->ScreenToClient(&p2);
294 CDC *dc = pWnd->GetDC();
296 StretchDIBits((HDC)*dc,
297 p.x,
298 p.y,
299 p2.x - p.x,
300 p2.y - p.y,
301 0,
302 0,
303 theApp.rect.right,
304 theApp.rect.bottom,
305 filterFunction ? filterData : pix+pitch,
306 bi,
307 DIB_RGB_COLORS,
308 SRCCOPY);
310 if (textMethod == 2 || (textMethod == 1 && !filterFunction)) // HACK: so that textMethod isn't changed
311 for (int slot = 0; slot < SCREEN_MESSAGE_SLOTS; slot++)
312 {
313 if (theApp.screenMessage[slot])
314 {
315 if ((theApp.screenMessageDuration[slot] < 0 ||
316 (int)(GetTickCount() - theApp.screenMessageTime[slot]) < theApp.screenMessageDuration[slot]) &&
317 (!theApp.disableStatusMessage || slot == 1 || slot == 2))
318 {
319 dc->SetBkMode(TRANSPARENT);
321 if (outlinedText)
322 {
323 dc->SetTextColor(textColor != 7 ? RGB(0, 0, 0) : RGB(255, 255, 255));
325 // draw black outline
326 const static int xd [8] = {-1, 0, 1, 1, 1, 0, -1, -1};
327 const static int yd [8] = {-1, -1, -1, 0, 1, 1, 1, 0};
328 for (int i = 0; i < 8; i++)
329 {
330 dc->TextOut(p.x+10+xd[i], p2.y - 20*(slot+1)+yd[i], theApp.screenMessageBuffer[slot]);
331 }
332 }
334 COLORREF color;
335 switch (textColor)
336 {
337 case 0:
338 color = RGB(255, 255, 255); break;
339 case 1:
340 color = RGB(255, 0, 0); break;
341 case 2:
342 color = RGB(255, 255, 0); break;
343 case 3:
344 color = RGB(0, 255, 0); break;
345 case 4:
346 color = RGB(0, 255, 255); break;
347 case 5:
348 color = RGB(0, 0, 255); break;
349 case 6:
350 color = RGB(255, 0, 255); break;
351 case 7:
352 color = RGB(0, 0, 0); break;
353 }
354 dc->SetTextColor(color);
356 // draw center text
357 dc->TextOut(p.x+10, p2.y - 20*(slot+1), theApp.screenMessageBuffer[slot]);
358 }
359 else
360 {
361 theApp.screenMessage[slot] = false;
362 }
363 }
364 }
366 pWnd->ReleaseDC(dc);
367 }
369 int GDIDisplay::selectFullScreenMode(GUID * *)
370 {
371 HWND wnd = GetDesktopWindow();
372 RECT r;
373 GetWindowRect(wnd, &r);
374 int w = (r.right - r.left) & 4095;
375 int h = (r.bottom - r.top) & 4095;
376 HDC dc = GetDC(wnd);
377 int c = GetDeviceCaps(dc, BITSPIXEL);
378 ReleaseDC(wnd, dc);
380 return (c << 24) | (w << 12) | h;
381 }
383 IDisplay *newGDIDisplay()
384 {
385 return new GDIDisplay();
386 }