diff 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 diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/win32/GDIDisplay.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,387 @@
     1.4 +#include "stdafx.h"
     1.5 +#include <cstdio>
     1.6 +
     1.7 +#include "resource.h"
     1.8 +#include "MainWnd.h"
     1.9 +#include "Reg.h"
    1.10 +#include "VBA.h"
    1.11 +
    1.12 +#include "../gba/GBAGlobals.h"
    1.13 +#include "../gb/gbGlobals.h"
    1.14 +#include "../common/Text.h"
    1.15 +#include "../version.h"
    1.16 +
    1.17 +extern u32 RGB_LOW_BITS_MASK;
    1.18 +extern int systemSpeed;
    1.19 +extern void winlog(const char *, ...);
    1.20 +extern int Init_2xSaI(u32);
    1.21 +
    1.22 +class GDIDisplay : public IDisplay
    1.23 +{
    1.24 +private:
    1.25 +	u8 *filterData;
    1.26 +	u8  info[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)];
    1.27 +public:
    1.28 +	GDIDisplay();
    1.29 +	virtual ~GDIDisplay();
    1.30 +
    1.31 +	virtual bool initialize();
    1.32 +	virtual void cleanup();
    1.33 +	virtual void render();
    1.34 +	virtual void checkFullScreen();
    1.35 +	virtual void renderMenu();
    1.36 +	virtual void clear();
    1.37 +	virtual DISPLAY_TYPE getType() { return GDI; };
    1.38 +	virtual void setOption(const char *, int) {}
    1.39 +	virtual int selectFullScreenMode(GUID * *);
    1.40 +};
    1.41 +
    1.42 +static int calculateShift(u32 mask)
    1.43 +{
    1.44 +	int m = 0;
    1.45 +
    1.46 +	while (mask)
    1.47 +	{
    1.48 +		m++;
    1.49 +		mask >>= 1;
    1.50 +	}
    1.51 +
    1.52 +	return m-5;
    1.53 +}
    1.54 +
    1.55 +GDIDisplay::GDIDisplay()
    1.56 +{
    1.57 +	filterData = (u8 *)malloc(4*16*256*256); // sufficient for 4x filters @ 32bit color depth
    1.58 +}
    1.59 +
    1.60 +GDIDisplay::~GDIDisplay()
    1.61 +{
    1.62 +	cleanup();
    1.63 +}
    1.64 +
    1.65 +void GDIDisplay::cleanup()
    1.66 +{
    1.67 +	if (filterData)
    1.68 +	{
    1.69 +		free(filterData);
    1.70 +		filterData = NULL;
    1.71 +	}
    1.72 +}
    1.73 +
    1.74 +bool GDIDisplay::initialize()
    1.75 +{
    1.76 +	CWnd *pWnd = theApp.m_pMainWnd;
    1.77 +
    1.78 +	theApp.mode320Available = false;
    1.79 +	theApp.mode640Available = false;
    1.80 +	theApp.mode800Available = false;
    1.81 +
    1.82 +	HDC         dc  = GetDC(NULL);
    1.83 +	HBITMAP     hbm = CreateCompatibleBitmap(dc, 1, 1);
    1.84 +	BITMAPINFO *bi  = (BITMAPINFO *)info;
    1.85 +	ZeroMemory(bi, sizeof(info));
    1.86 +	bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    1.87 +	GetDIBits(dc, hbm, 0, 1, NULL, (LPBITMAPINFO)info, DIB_RGB_COLORS);
    1.88 +	GetDIBits(dc, hbm, 0, 1, NULL, (LPBITMAPINFO)info, DIB_RGB_COLORS);
    1.89 +	DeleteObject(hbm);
    1.90 +	ReleaseDC(NULL, dc);
    1.91 +
    1.92 +	if (bi->bmiHeader.biCompression == BI_BITFIELDS)
    1.93 +	{
    1.94 +		systemColorDepth = bi->bmiHeader.biBitCount;
    1.95 +		if (systemColorDepth == 15)
    1.96 +			systemColorDepth = 16;
    1.97 +		systemRedShift   = calculateShift(*((DWORD *)&bi->bmiColors[0]));
    1.98 +		systemGreenShift = calculateShift(*((DWORD *)&bi->bmiColors[1]));
    1.99 +		systemBlueShift  = calculateShift(*((DWORD *)&bi->bmiColors[2]));
   1.100 +		if (systemColorDepth == 16)
   1.101 +		{
   1.102 +			if (systemGreenShift == 6)
   1.103 +			{
   1.104 +				Init_2xSaI(565);
   1.105 +				RGB_LOW_BITS_MASK = 0x821;
   1.106 +			}
   1.107 +			else
   1.108 +			{
   1.109 +				Init_2xSaI(555);
   1.110 +				RGB_LOW_BITS_MASK = 0x421;
   1.111 +			}
   1.112 +		}
   1.113 +		else if (systemColorDepth == 32)
   1.114 +			Init_2xSaI(32);
   1.115 +	}
   1.116 +	else
   1.117 +	{
   1.118 +		systemColorDepth = 32;
   1.119 +		systemRedShift   = 19;
   1.120 +		systemGreenShift = 11;
   1.121 +		systemBlueShift  = 3;
   1.122 +
   1.123 +		Init_2xSaI(32);
   1.124 +	}
   1.125 +	theApp.fsColorDepth = systemColorDepth;
   1.126 +	if (systemColorDepth == 24)
   1.127 +		theApp.filterFunction = NULL;
   1.128 +#ifdef MMX
   1.129 +	if (!theApp.disableMMX)
   1.130 +		cpu_mmx = theApp.detectMMX();
   1.131 +	else
   1.132 +		cpu_mmx = 0;
   1.133 +#endif
   1.134 +
   1.135 +	switch (systemColorDepth)
   1.136 +	{
   1.137 +	case 16:
   1.138 +	{
   1.139 +		for (int i = 0; i < 0x10000; i++)
   1.140 +		{
   1.141 +			systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
   1.142 +			                      (((i & 0x3e0) >> 5) << systemGreenShift) |
   1.143 +			                      (((i & 0x7c00) >> 10) << systemBlueShift);
   1.144 +		}
   1.145 +		break;
   1.146 +	}
   1.147 +	case 24:
   1.148 +	case 32:
   1.149 +	{
   1.150 +		for (int i = 0; i < 0x10000; i++)
   1.151 +		{
   1.152 +			systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
   1.153 +			                      (((i & 0x3e0) >> 5) << systemGreenShift) |
   1.154 +			                      (((i & 0x7c00) >> 10) << systemBlueShift);
   1.155 +		}
   1.156 +		break;
   1.157 +	}
   1.158 +	}
   1.159 +	theApp.updateFilter();
   1.160 +	theApp.updateIFB();
   1.161 +
   1.162 +	pWnd->DragAcceptFiles(TRUE);
   1.163 +
   1.164 +	return TRUE;
   1.165 +}
   1.166 +
   1.167 +void GDIDisplay::clear()
   1.168 +{}
   1.169 +
   1.170 +void GDIDisplay::renderMenu()
   1.171 +{
   1.172 +	checkFullScreen();
   1.173 +	theApp.m_pMainWnd->DrawMenuBar();
   1.174 +}
   1.175 +
   1.176 +void GDIDisplay::checkFullScreen()
   1.177 +{}
   1.178 +
   1.179 +void GDIDisplay::render()
   1.180 +{
   1.181 +	void (*filterFunction)(u8 *, u32, u8 *, u8 *, u32, int, int) = theApp.filterFunction;
   1.182 +	int  filterWidth = theApp.filterWidth, filterHeight = theApp.filterHeight;
   1.183 +/*
   1.184 +    if(textMethod == 1)
   1.185 +    {
   1.186 +        int copyX = 240, copyY = 160;
   1.187 +        if(systemCartridgeType == 1)
   1.188 +            if(gbBorderOn) copyX = 256, copyY = 224;
   1.189 +            else           copyX = 160, copyY = 144;
   1.190 +
   1.191 +        extern void Simple1x(u8*,u32,u8*,u8*,u32,int,int);
   1.192 +        filterFunction = Simple1x;
   1.193 +        filterWidth = copyX*2;
   1.194 +        filterHeight = copyY*2;
   1.195 +    }
   1.196 + */
   1.197 +	BITMAPINFO *bi = (BITMAPINFO *)info;
   1.198 +	bi->bmiHeader.biWidth  = filterWidth+1;
   1.199 +	bi->bmiHeader.biHeight = -filterHeight;
   1.200 +
   1.201 +	int pitch = filterWidth * 2 + 4;
   1.202 +	if (systemColorDepth == 32)
   1.203 +		pitch = filterWidth * 4 + 4;
   1.204 +	// FIXME: is the 24bit color depth still being used nowadays?
   1.205 +	else if (systemColorDepth == 24)
   1.206 +		pitch = filterWidth * 3;
   1.207 +
   1.208 +	// FIXME: is this working if systemColorDepth == 24?
   1.209 +	int filterPitch = theApp.rect.right*2;
   1.210 +	if (systemColorDepth == 32)
   1.211 +		filterPitch = theApp.rect.right*4;
   1.212 +	else if (systemColorDepth == 24)
   1.213 +		filterPitch = theApp.rect.right*3;
   1.214 +
   1.215 +/*
   1.216 +	// HACK: see below
   1.217 +	if (textMethod == 1 && !filterFunction)
   1.218 +	{
   1.219 +		textMethod = 0; // must not be after systemMessage!
   1.220 +		systemMessage(
   1.221 +		    0,
   1.222 +		    "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...\"");
   1.223 +	}
   1.224 +*/
   1.225 +
   1.226 +	if (filterFunction)
   1.227 +	{
   1.228 +		bi->bmiHeader.biWidth  = theApp.rect.right;
   1.229 +		bi->bmiHeader.biHeight = -theApp.rect.bottom;
   1.230 +
   1.231 +		(*filterFunction)(pix + pitch,
   1.232 +						  pitch,
   1.233 +						  (u8 *)theApp.delta,
   1.234 +						  (u8 *)filterData,
   1.235 +						  filterPitch,
   1.236 +						  filterWidth,
   1.237 +						  filterHeight);
   1.238 +	}
   1.239 +
   1.240 +	if (theApp.showSpeed && theApp.videoOption > VIDEO_4X)
   1.241 +	{
   1.242 +		char buffer[30];
   1.243 +		if (theApp.showSpeed == 1)
   1.244 +			sprintf(buffer, "%3d%%", systemSpeed);
   1.245 +		else
   1.246 +			sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
   1.247 +			        systemFrameSkip,
   1.248 +			        theApp.showRenderedFrames);
   1.249 +
   1.250 +		if (filterFunction)
   1.251 +		{
   1.252 +			if (theApp.showSpeedTransparent)
   1.253 +				drawTextTransp((u8 *)filterData,
   1.254 +				               filterPitch,
   1.255 +				               theApp.rect.left+10,
   1.256 +				               theApp.rect.bottom-10,
   1.257 +				               buffer);
   1.258 +			else
   1.259 +				drawText((u8 *)filterData,
   1.260 +				         filterPitch,
   1.261 +			             theApp.rect.left+10,
   1.262 +			             theApp.rect.bottom-10,
   1.263 +				         buffer);
   1.264 +		}
   1.265 +		else
   1.266 +		{
   1.267 +			if (theApp.showSpeedTransparent)
   1.268 +				drawTextTransp((u8 *)pix,
   1.269 +				               pitch,
   1.270 +				               theApp.rect.left+10,
   1.271 +				               theApp.rect.bottom-10,
   1.272 +				               buffer);
   1.273 +			else
   1.274 +				drawText((u8 *)pix,
   1.275 +				         pitch,
   1.276 +			             theApp.rect.left+10,
   1.277 +			             theApp.rect.bottom-10,
   1.278 +				         buffer);
   1.279 +		}
   1.280 +	}
   1.281 +
   1.282 +	if (textMethod == 1 && filterFunction)
   1.283 +	{
   1.284 +		DrawTextMessages((u8 *)filterData, filterPitch, theApp.rect.left, theApp.rect.bottom);
   1.285 +	}
   1.286 +
   1.287 +	POINT p;
   1.288 +	p.x = theApp.dest.left;
   1.289 +	p.y = theApp.dest.top;
   1.290 +	CWnd *pWnd = theApp.m_pMainWnd;
   1.291 +	pWnd->ScreenToClient(&p);
   1.292 +	POINT p2;
   1.293 +	p2.x = theApp.dest.right;
   1.294 +	p2.y = theApp.dest.bottom;
   1.295 +	pWnd->ScreenToClient(&p2);
   1.296 +
   1.297 +	CDC *dc = pWnd->GetDC();
   1.298 +
   1.299 +	StretchDIBits((HDC)*dc,
   1.300 +	              p.x,
   1.301 +	              p.y,
   1.302 +	              p2.x - p.x,
   1.303 +	              p2.y - p.y,
   1.304 +	              0,
   1.305 +	              0,
   1.306 +	              theApp.rect.right,
   1.307 +	              theApp.rect.bottom,
   1.308 +	              filterFunction ? filterData : pix+pitch,
   1.309 +	              bi,
   1.310 +	              DIB_RGB_COLORS,
   1.311 +	              SRCCOPY);
   1.312 +
   1.313 +	if (textMethod == 2 || (textMethod == 1 && !filterFunction)) // HACK: so that textMethod isn't changed
   1.314 +		for (int slot = 0; slot < SCREEN_MESSAGE_SLOTS; slot++)
   1.315 +		{
   1.316 +			if (theApp.screenMessage[slot])
   1.317 +			{
   1.318 +				if ((theApp.screenMessageDuration[slot] < 0 || 
   1.319 +					(int)(GetTickCount() - theApp.screenMessageTime[slot]) < theApp.screenMessageDuration[slot]) &&
   1.320 +				    (!theApp.disableStatusMessage || slot == 1 || slot == 2))
   1.321 +				{
   1.322 +					dc->SetBkMode(TRANSPARENT);
   1.323 +
   1.324 +					if (outlinedText)
   1.325 +					{
   1.326 +						dc->SetTextColor(textColor != 7 ? RGB(0, 0, 0) : RGB(255, 255, 255));
   1.327 +
   1.328 +						// draw black outline
   1.329 +						const static int xd [8] = {-1, 0, 1, 1, 1, 0, -1, -1};
   1.330 +						const static int yd [8] = {-1, -1, -1, 0, 1, 1, 1, 0};
   1.331 +						for (int i = 0; i < 8; i++)
   1.332 +						{
   1.333 +							dc->TextOut(p.x+10+xd[i], p2.y - 20*(slot+1)+yd[i], theApp.screenMessageBuffer[slot]);
   1.334 +						}
   1.335 +					}
   1.336 +
   1.337 +					COLORREF color;
   1.338 +					switch (textColor)
   1.339 +					{
   1.340 +					case 0:
   1.341 +						color = RGB(255, 255, 255); break;
   1.342 +					case 1:
   1.343 +						color = RGB(255, 0, 0); break;
   1.344 +					case 2:
   1.345 +						color = RGB(255, 255, 0); break;
   1.346 +					case 3:
   1.347 +						color = RGB(0, 255, 0); break;
   1.348 +					case 4:
   1.349 +						color = RGB(0, 255, 255); break;
   1.350 +					case 5:
   1.351 +						color = RGB(0, 0, 255); break;
   1.352 +					case 6:
   1.353 +						color = RGB(255, 0, 255); break;
   1.354 +					case 7:
   1.355 +						color = RGB(0, 0, 0); break;
   1.356 +					}
   1.357 +					dc->SetTextColor(color);
   1.358 +
   1.359 +					// draw center text
   1.360 +					dc->TextOut(p.x+10, p2.y - 20*(slot+1), theApp.screenMessageBuffer[slot]);
   1.361 +				}
   1.362 +				else
   1.363 +				{
   1.364 +					theApp.screenMessage[slot] = false;
   1.365 +				}
   1.366 +			}
   1.367 +		}
   1.368 +
   1.369 +	pWnd->ReleaseDC(dc);
   1.370 +}
   1.371 +
   1.372 +int GDIDisplay::selectFullScreenMode(GUID * *)
   1.373 +{
   1.374 +	HWND wnd = GetDesktopWindow();
   1.375 +	RECT r;
   1.376 +	GetWindowRect(wnd, &r);
   1.377 +	int w  = (r.right - r.left) & 4095;
   1.378 +	int h  = (r.bottom - r.top) & 4095;
   1.379 +	HDC dc = GetDC(wnd);
   1.380 +	int c  = GetDeviceCaps(dc, BITSPIXEL);
   1.381 +	ReleaseDC(wnd, dc);
   1.382 +
   1.383 +	return (c << 24) | (w << 12) | h;
   1.384 +}
   1.385 +
   1.386 +IDisplay *newGDIDisplay()
   1.387 +{
   1.388 +	return new GDIDisplay();
   1.389 +}
   1.390 +