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