rlm@1
|
1 #include "stdafx.h"
|
rlm@1
|
2
|
rlm@1
|
3 #define DIRECT3D_VERSION 0x0800
|
rlm@1
|
4 #include "d3d8.h"
|
rlm@1
|
5 #include "d3dx8.h"
|
rlm@1
|
6
|
rlm@1
|
7 #include "resource.h"
|
rlm@1
|
8 #include "MainWnd.h"
|
rlm@1
|
9 #include "Reg.h"
|
rlm@1
|
10 #include "VBA.h"
|
rlm@1
|
11
|
rlm@1
|
12 //#include "../common/System.h"
|
rlm@1
|
13 #include "../gba/GBAGlobals.h"
|
rlm@1
|
14 #include "../gb/gbGlobals.h"
|
rlm@1
|
15 #include "../common/Text.h"
|
rlm@1
|
16 #include "../version.h"
|
rlm@1
|
17
|
rlm@1
|
18 #ifdef MMX
|
rlm@1
|
19 extern "C" bool cpu_mmx;
|
rlm@1
|
20
|
rlm@1
|
21 extern bool detectMMX();
|
rlm@1
|
22 #endif
|
rlm@1
|
23
|
rlm@1
|
24 extern int Init_2xSaI(u32);
|
rlm@1
|
25 extern void directXMessage(const char *);
|
rlm@1
|
26 extern void winlog(const char *, ...);
|
rlm@1
|
27
|
rlm@1
|
28 typedef struct _D3DTLVERTEX
|
rlm@1
|
29 {
|
rlm@1
|
30 float sx; /* Screen coordinates */
|
rlm@1
|
31 float sy;
|
rlm@1
|
32 float sz;
|
rlm@1
|
33 float rhw; /* Reciprocal of homogeneous w */
|
rlm@1
|
34 D3DCOLOR color; /* Vertex color */
|
rlm@1
|
35 float tu; /* Texture coordinates */
|
rlm@1
|
36 float tv;
|
rlm@1
|
37 _D3DTLVERTEX() { }
|
rlm@1
|
38 _D3DTLVERTEX(const D3DVECTOR& v, float _rhw,
|
rlm@1
|
39 D3DCOLOR _color,
|
rlm@1
|
40 float _tu, float _tv)
|
rlm@1
|
41 {
|
rlm@1
|
42 sx = v.x; sy = v.y; sz = v.z; rhw = _rhw;
|
rlm@1
|
43 color = _color;
|
rlm@1
|
44 tu = _tu; tv = _tv;
|
rlm@1
|
45 }
|
rlm@1
|
46 } D3DTLVERTEX, *LPD3DTLVERTEX;
|
rlm@1
|
47
|
rlm@1
|
48 #define D3DFVF_TLVERTEX D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1
|
rlm@1
|
49
|
rlm@1
|
50 class Direct3DDisplay : public IDisplay
|
rlm@1
|
51 {
|
rlm@1
|
52 public:
|
rlm@1
|
53 Direct3DDisplay();
|
rlm@1
|
54 virtual ~Direct3DDisplay();
|
rlm@1
|
55
|
rlm@1
|
56 virtual bool initialize();
|
rlm@1
|
57 virtual void cleanup();
|
rlm@1
|
58 virtual void render();
|
rlm@1
|
59 virtual void checkFullScreen();
|
rlm@1
|
60 virtual void renderMenu();
|
rlm@1
|
61 virtual void clear();
|
rlm@1
|
62 virtual bool changeRenderSize(int w, int h);
|
rlm@1
|
63 virtual void resize(int w, int h);
|
rlm@1
|
64 virtual DISPLAY_TYPE getType() { return DIRECT_3D; };
|
rlm@1
|
65 virtual void setOption(const char *, int);
|
rlm@1
|
66 virtual int selectFullScreenMode(GUID * *);
|
rlm@1
|
67
|
rlm@1
|
68 private:
|
rlm@1
|
69 HINSTANCE d3dDLL;
|
rlm@1
|
70 LPDIRECT3D8 pD3D;
|
rlm@1
|
71 LPDIRECT3DDEVICE8 pDevice;
|
rlm@1
|
72 LPDIRECT3DTEXTURE8 pTexture;
|
rlm@1
|
73 D3DSURFACE_DESC dsdBackBuffer;
|
rlm@1
|
74 D3DPRESENT_PARAMETERS dpp;
|
rlm@1
|
75 D3DFORMAT screenFormat;
|
rlm@1
|
76 int width;
|
rlm@1
|
77 int height;
|
rlm@1
|
78 bool filterDisabled;
|
rlm@1
|
79 ID3DXFont *pFont;
|
rlm@1
|
80 bool failed;
|
rlm@1
|
81 unsigned int textureSize;
|
rlm@1
|
82 D3DTLVERTEX verts[4];
|
rlm@1
|
83
|
rlm@1
|
84
|
rlm@1
|
85 void restoreDeviceObjects();
|
rlm@1
|
86 void invalidateDeviceObjects();
|
rlm@1
|
87 bool initializeOffscreen(int w, int h);
|
rlm@1
|
88 void updateFiltering(int);
|
rlm@1
|
89 void calculateVertices();
|
rlm@1
|
90 };
|
rlm@1
|
91
|
rlm@1
|
92 Direct3DDisplay::Direct3DDisplay()
|
rlm@1
|
93 {
|
rlm@1
|
94 d3dDLL = NULL;
|
rlm@1
|
95 pD3D = NULL;
|
rlm@1
|
96 pDevice = NULL;
|
rlm@1
|
97 pTexture = NULL;
|
rlm@1
|
98 pFont = NULL;
|
rlm@1
|
99 screenFormat = D3DFMT_R5G6B5;
|
rlm@1
|
100 width = 0;
|
rlm@1
|
101 height = 0;
|
rlm@1
|
102 filterDisabled = false;
|
rlm@1
|
103 failed = false;
|
rlm@1
|
104 textureSize = 0;
|
rlm@1
|
105 }
|
rlm@1
|
106
|
rlm@1
|
107 Direct3DDisplay::~Direct3DDisplay()
|
rlm@1
|
108 {
|
rlm@1
|
109 cleanup();
|
rlm@1
|
110 }
|
rlm@1
|
111
|
rlm@1
|
112 void Direct3DDisplay::cleanup()
|
rlm@1
|
113 {
|
rlm@1
|
114 if (pD3D != NULL)
|
rlm@1
|
115 {
|
rlm@1
|
116 if (pFont)
|
rlm@1
|
117 {
|
rlm@1
|
118 pFont->Release();
|
rlm@1
|
119 pFont = NULL;
|
rlm@1
|
120 }
|
rlm@1
|
121
|
rlm@1
|
122 if (pTexture)
|
rlm@1
|
123 {
|
rlm@1
|
124 pTexture->Release();
|
rlm@1
|
125 pTexture = NULL;
|
rlm@1
|
126 }
|
rlm@1
|
127
|
rlm@1
|
128 if (pDevice)
|
rlm@1
|
129 {
|
rlm@1
|
130 pDevice->Release();
|
rlm@1
|
131 pDevice = NULL;
|
rlm@1
|
132 }
|
rlm@1
|
133
|
rlm@1
|
134 pD3D->Release();
|
rlm@1
|
135 pD3D = NULL;
|
rlm@1
|
136
|
rlm@1
|
137 if (d3dDLL != NULL)
|
rlm@1
|
138 {
|
rlm@1
|
139 FreeLibrary(d3dDLL);
|
rlm@1
|
140 d3dDLL = NULL;
|
rlm@1
|
141 }
|
rlm@1
|
142 }
|
rlm@1
|
143 }
|
rlm@1
|
144
|
rlm@1
|
145 bool Direct3DDisplay::initialize()
|
rlm@1
|
146 {
|
rlm@1
|
147 CWnd *pWnd = theApp.m_pMainWnd;
|
rlm@1
|
148
|
rlm@1
|
149 d3dDLL = LoadLibrary("D3D8.DLL");
|
rlm@1
|
150 LPDIRECT3D8 (WINAPI *D3DCreate)(UINT);
|
rlm@1
|
151 if (d3dDLL != NULL)
|
rlm@1
|
152 {
|
rlm@1
|
153 D3DCreate = (LPDIRECT3D8 (WINAPI *)(UINT))
|
rlm@1
|
154 GetProcAddress(d3dDLL, "Direct3DCreate8");
|
rlm@1
|
155
|
rlm@1
|
156 if (D3DCreate == NULL)
|
rlm@1
|
157 {
|
rlm@1
|
158 directXMessage("Direct3DCreate8");
|
rlm@1
|
159 return FALSE;
|
rlm@1
|
160 }
|
rlm@1
|
161 }
|
rlm@1
|
162 else
|
rlm@1
|
163 {
|
rlm@1
|
164 directXMessage("D3D8.DLL");
|
rlm@1
|
165 return FALSE;
|
rlm@1
|
166 }
|
rlm@1
|
167
|
rlm@1
|
168 pD3D = D3DCreate(120);
|
rlm@1
|
169
|
rlm@1
|
170 if (pD3D == NULL)
|
rlm@1
|
171 {
|
rlm@1
|
172 winlog("Error creating Direct3D object\n");
|
rlm@1
|
173 return FALSE;
|
rlm@1
|
174 }
|
rlm@1
|
175
|
rlm@1
|
176 theApp.mode320Available = false;
|
rlm@1
|
177 theApp.mode640Available = false;
|
rlm@1
|
178 theApp.mode800Available = false;
|
rlm@1
|
179
|
rlm@1
|
180 D3DDISPLAYMODE mode;
|
rlm@1
|
181 pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode);
|
rlm@1
|
182
|
rlm@1
|
183 switch (mode.Format)
|
rlm@1
|
184 {
|
rlm@1
|
185 case D3DFMT_R8G8B8:
|
rlm@1
|
186 systemColorDepth = 24;
|
rlm@1
|
187 systemRedShift = 19;
|
rlm@1
|
188 systemGreenShift = 11;
|
rlm@1
|
189 systemBlueShift = 3;
|
rlm@1
|
190 break;
|
rlm@1
|
191 case D3DFMT_X8R8G8B8:
|
rlm@1
|
192 systemColorDepth = 32;
|
rlm@1
|
193 systemRedShift = 19;
|
rlm@1
|
194 systemGreenShift = 11;
|
rlm@1
|
195 systemBlueShift = 3;
|
rlm@1
|
196 Init_2xSaI(32);
|
rlm@1
|
197 break;
|
rlm@1
|
198 case D3DFMT_R5G6B5:
|
rlm@1
|
199 systemColorDepth = 16;
|
rlm@1
|
200 systemRedShift = 11;
|
rlm@1
|
201 systemGreenShift = 6;
|
rlm@1
|
202 systemBlueShift = 0;
|
rlm@1
|
203 Init_2xSaI(565);
|
rlm@1
|
204 break;
|
rlm@1
|
205 case D3DFMT_X1R5G5B5:
|
rlm@1
|
206 systemColorDepth = 16;
|
rlm@1
|
207 systemRedShift = 10;
|
rlm@1
|
208 systemGreenShift = 5;
|
rlm@1
|
209 systemBlueShift = 0;
|
rlm@1
|
210 Init_2xSaI(555);
|
rlm@1
|
211 break;
|
rlm@1
|
212 default:
|
rlm@1
|
213 systemMessage(0, "Unsupport D3D format %d", mode.Format);
|
rlm@1
|
214 return false;
|
rlm@1
|
215 }
|
rlm@1
|
216 theApp.fsColorDepth = systemColorDepth;
|
rlm@1
|
217
|
rlm@1
|
218 #ifdef MMX
|
rlm@1
|
219 if (!theApp.disableMMX)
|
rlm@1
|
220 cpu_mmx = theApp.detectMMX();
|
rlm@1
|
221 else
|
rlm@1
|
222 cpu_mmx = 0;
|
rlm@1
|
223 #endif
|
rlm@1
|
224
|
rlm@1
|
225 screenFormat = mode.Format;
|
rlm@1
|
226
|
rlm@1
|
227 // check for available fullscreen modes
|
rlm@1
|
228 ZeroMemory(&dpp, sizeof(dpp));
|
rlm@1
|
229 dpp.Windowed = TRUE;
|
rlm@1
|
230 dpp.BackBufferFormat = mode.Format;
|
rlm@1
|
231 dpp.BackBufferCount = 1;
|
rlm@1
|
232 dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
rlm@1
|
233 dpp.BackBufferWidth = theApp.surfaceSizeX;
|
rlm@1
|
234 dpp.BackBufferHeight = theApp.surfaceSizeY;
|
rlm@1
|
235
|
rlm@1
|
236 HRESULT hret = pD3D->CreateDevice(D3DADAPTER_DEFAULT,
|
rlm@1
|
237 D3DDEVTYPE_HAL,
|
rlm@1
|
238 pWnd->GetSafeHwnd(),
|
rlm@1
|
239 D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE,
|
rlm@1
|
240 &dpp,
|
rlm@1
|
241 &pDevice);
|
rlm@1
|
242 if (!SUCCEEDED(hret))
|
rlm@1
|
243 {
|
rlm@1
|
244 winlog("Error creating Direct3DDevice %08x\n", hret);
|
rlm@1
|
245 return false;
|
rlm@1
|
246 }
|
rlm@1
|
247
|
rlm@1
|
248 restoreDeviceObjects();
|
rlm@1
|
249
|
rlm@1
|
250 switch (systemColorDepth)
|
rlm@1
|
251 {
|
rlm@1
|
252 case 16:
|
rlm@1
|
253 {
|
rlm@1
|
254 for (int i = 0; i < 0x10000; i++)
|
rlm@1
|
255 {
|
rlm@1
|
256 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
|
rlm@1
|
257 (((i & 0x3e0) >> 5) << systemGreenShift) |
|
rlm@1
|
258 (((i & 0x7c00) >> 10) << systemBlueShift);
|
rlm@1
|
259 }
|
rlm@1
|
260 break;
|
rlm@1
|
261 }
|
rlm@1
|
262 case 24:
|
rlm@1
|
263 case 32:
|
rlm@1
|
264 {
|
rlm@1
|
265 for (int i = 0; i < 0x10000; i++)
|
rlm@1
|
266 {
|
rlm@1
|
267 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
|
rlm@1
|
268 (((i & 0x3e0) >> 5) << systemGreenShift) |
|
rlm@1
|
269 (((i & 0x7c00) >> 10) << systemBlueShift);
|
rlm@1
|
270 }
|
rlm@1
|
271 break;
|
rlm@1
|
272 }
|
rlm@1
|
273 }
|
rlm@1
|
274
|
rlm@1
|
275 theApp.updateFilter();
|
rlm@1
|
276 theApp.updateIFB();
|
rlm@1
|
277
|
rlm@1
|
278 if (failed)
|
rlm@1
|
279 return false;
|
rlm@1
|
280
|
rlm@1
|
281 pWnd->DragAcceptFiles(TRUE);
|
rlm@1
|
282
|
rlm@1
|
283 return TRUE;
|
rlm@1
|
284 }
|
rlm@1
|
285
|
rlm@1
|
286 bool Direct3DDisplay::initializeOffscreen(int w, int h)
|
rlm@1
|
287 {
|
rlm@1
|
288 int size = 256;
|
rlm@1
|
289 if (w > 512 || h > 512)
|
rlm@1
|
290 size = 1024;
|
rlm@1
|
291 else if (w > 256 || h > 256)
|
rlm@1
|
292 size = 512;
|
rlm@1
|
293 textureSize = size;
|
rlm@1
|
294
|
rlm@1
|
295 UINT ww = size;
|
rlm@1
|
296 UINT hh = size;
|
rlm@1
|
297 D3DFORMAT format = screenFormat;
|
rlm@1
|
298
|
rlm@1
|
299 if (SUCCEEDED(D3DXCheckTextureRequirements(pDevice,
|
rlm@1
|
300 &ww,
|
rlm@1
|
301 &hh,
|
rlm@1
|
302 NULL,
|
rlm@1
|
303 0,
|
rlm@1
|
304 &format,
|
rlm@1
|
305 D3DPOOL_MANAGED)))
|
rlm@1
|
306 {
|
rlm@1
|
307 if ((int)ww < w || (int)hh < h)
|
rlm@1
|
308 {
|
rlm@1
|
309 if (theApp.filterFunction)
|
rlm@1
|
310 {
|
rlm@1
|
311 filterDisabled = true;
|
rlm@1
|
312 theApp.filterFunction = NULL;
|
rlm@1
|
313 systemMessage(0, "3D card cannot support needed texture size for filter function. Disabling it");
|
rlm@1
|
314 }
|
rlm@1
|
315 }
|
rlm@1
|
316 else
|
rlm@1
|
317 filterDisabled = false;
|
rlm@1
|
318 if (SUCCEEDED(D3DXCreateTexture(pDevice,
|
rlm@1
|
319 ww,
|
rlm@1
|
320 hh,
|
rlm@1
|
321 0,
|
rlm@1
|
322 0,
|
rlm@1
|
323 format,
|
rlm@1
|
324 D3DPOOL_MANAGED,
|
rlm@1
|
325 &pTexture)))
|
rlm@1
|
326 {
|
rlm@1
|
327 width = w;
|
rlm@1
|
328 height = h;
|
rlm@1
|
329 return true;
|
rlm@1
|
330 }
|
rlm@1
|
331 }
|
rlm@1
|
332 return false;
|
rlm@1
|
333 }
|
rlm@1
|
334
|
rlm@1
|
335 void Direct3DDisplay::updateFiltering(int filter)
|
rlm@1
|
336 {
|
rlm@1
|
337 switch (filter)
|
rlm@1
|
338 {
|
rlm@1
|
339 default:
|
rlm@1
|
340 case 0:
|
rlm@1
|
341 // point filtering
|
rlm@1
|
342 pDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_POINT);
|
rlm@1
|
343 pDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
|
rlm@1
|
344 pDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
|
rlm@1
|
345 break;
|
rlm@1
|
346 case 1:
|
rlm@1
|
347 // bilinear
|
rlm@1
|
348 pDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
|
rlm@1
|
349 pDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
|
rlm@1
|
350 pDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
|
rlm@1
|
351 break;
|
rlm@1
|
352 }
|
rlm@1
|
353 }
|
rlm@1
|
354
|
rlm@1
|
355 void Direct3DDisplay::restoreDeviceObjects()
|
rlm@1
|
356 {
|
rlm@1
|
357 // Store render target surface desc
|
rlm@1
|
358 LPDIRECT3DSURFACE8 pBackBuffer;
|
rlm@1
|
359 HRESULT hr;
|
rlm@1
|
360 if (SUCCEEDED(hr = pDevice->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer)))
|
rlm@1
|
361 {
|
rlm@1
|
362 pBackBuffer->GetDesc(&dsdBackBuffer);
|
rlm@1
|
363 pBackBuffer->Release();
|
rlm@1
|
364 }
|
rlm@1
|
365 else
|
rlm@1
|
366 systemMessage(0, "Failed GetBackBuffer %08x", hr);
|
rlm@1
|
367
|
rlm@1
|
368 // Set up the texture
|
rlm@1
|
369 pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
rlm@1
|
370 pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
rlm@1
|
371 pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
rlm@1
|
372
|
rlm@1
|
373 int filter = regQueryDwordValue("d3dFilter", 0);
|
rlm@1
|
374 if (filter < 0 || filter > 3)
|
rlm@1
|
375 filter = 0;
|
rlm@1
|
376 updateFiltering(filter);
|
rlm@1
|
377
|
rlm@1
|
378 // Set miscellaneous render states
|
rlm@1
|
379 pDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE);
|
rlm@1
|
380 pDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
|
rlm@1
|
381
|
rlm@1
|
382 // Set the projection matrix
|
rlm@1
|
383 D3DXMATRIX matProj;
|
rlm@1
|
384 FLOAT fAspect = ((FLOAT)dsdBackBuffer.Width) / dsdBackBuffer.Height;
|
rlm@1
|
385 D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, fAspect, 1.0f, 100.0f);
|
rlm@1
|
386 pDevice->SetTransform(D3DTS_PROJECTION, &matProj);
|
rlm@1
|
387
|
rlm@1
|
388 // turn off lighting
|
rlm@1
|
389 pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
|
rlm@1
|
390
|
rlm@1
|
391 if (pFont)
|
rlm@1
|
392 {
|
rlm@1
|
393 pFont->Release();
|
rlm@1
|
394 pFont = NULL;
|
rlm@1
|
395 }
|
rlm@1
|
396 // Create a D3D font using D3DX
|
rlm@1
|
397 HFONT hFont = CreateFont(14, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
|
rlm@1
|
398 ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
|
rlm@1
|
399 ANTIALIASED_QUALITY, FF_DONTCARE, "Arial");
|
rlm@1
|
400 D3DXCreateFont(pDevice, hFont, &pFont);
|
rlm@1
|
401 }
|
rlm@1
|
402
|
rlm@1
|
403 void Direct3DDisplay::clear()
|
rlm@1
|
404 {}
|
rlm@1
|
405
|
rlm@1
|
406 void Direct3DDisplay::renderMenu()
|
rlm@1
|
407 {
|
rlm@1
|
408 checkFullScreen();
|
rlm@1
|
409 if (theApp.m_pMainWnd)
|
rlm@1
|
410 theApp.m_pMainWnd->DrawMenuBar();
|
rlm@1
|
411 }
|
rlm@1
|
412
|
rlm@1
|
413 void Direct3DDisplay::checkFullScreen()
|
rlm@1
|
414 {
|
rlm@1
|
415 // if(tripleBuffering)
|
rlm@1
|
416 // pDirect3D->FlipToGDISurface();
|
rlm@1
|
417 }
|
rlm@1
|
418
|
rlm@1
|
419 void Direct3DDisplay::calculateVertices()
|
rlm@1
|
420 {
|
rlm@1
|
421 // color
|
rlm@1
|
422 D3DCOLOR col = 0xFFFFFFFF;
|
rlm@1
|
423
|
rlm@1
|
424 // calculate rhw
|
rlm@1
|
425 FLOAT z = 1.0f;
|
rlm@1
|
426 FLOAT rhw = 1.0f / (z * 990.0f + 10.0f);
|
rlm@1
|
427
|
rlm@1
|
428 // -0.5f is necessary in order to match texture alignment to display pixels
|
rlm@1
|
429 FLOAT left = -0.5f;
|
rlm@1
|
430 FLOAT right = dpp.BackBufferWidth - 0.5f;
|
rlm@1
|
431 FLOAT top = -0.5f;
|
rlm@1
|
432 FLOAT bottom = dpp.BackBufferHeight - 0.5f;
|
rlm@1
|
433
|
rlm@1
|
434 FLOAT textureX = (FLOAT)theApp.rect.right / (FLOAT)textureSize;
|
rlm@1
|
435 FLOAT textureY = (FLOAT)theApp.rect.bottom / (FLOAT)textureSize;
|
rlm@1
|
436
|
rlm@1
|
437 //#define D3D_DRAW_SINGLE_RECTANGLE
|
rlm@1
|
438 #ifdef D3D_DRAW_SINGLE_RECTANGLE
|
rlm@1
|
439 // set up a rectangle
|
rlm@1
|
440 verts[0] = D3DTLVERTEX(D3DXVECTOR3(left, top, z), rhw, col, 0.0f, 0.0f);
|
rlm@1
|
441 verts[1] = D3DTLVERTEX(D3DXVECTOR3(right, top, z), rhw, col, textureX, 0.0f);
|
rlm@1
|
442 verts[2] = D3DTLVERTEX(D3DXVECTOR3(right, bottom, z), rhw, col, textureX, textureY);
|
rlm@1
|
443 verts[3] = D3DTLVERTEX(D3DXVECTOR3(left, bottom, z), rhw, col, 0.0f, textureY);
|
rlm@1
|
444 #else
|
rlm@1
|
445 // set up triangles
|
rlm@1
|
446 verts[0] = D3DTLVERTEX(D3DXVECTOR3(left, bottom, z), rhw, col, 0.0f, textureY);
|
rlm@1
|
447 verts[1] = D3DTLVERTEX(D3DXVECTOR3(left, top, z), rhw, col, 0.0f, 0.0f);
|
rlm@1
|
448 verts[2] = D3DTLVERTEX(D3DXVECTOR3(right, bottom, z), rhw, col, textureX, textureY);
|
rlm@1
|
449 verts[3] = D3DTLVERTEX(D3DXVECTOR3(right, top, z), rhw, col, textureX, 0.0f);
|
rlm@1
|
450 #endif
|
rlm@1
|
451 }
|
rlm@1
|
452
|
rlm@1
|
453 void Direct3DDisplay::render()
|
rlm@1
|
454 {
|
rlm@1
|
455 if (!pDevice)
|
rlm@1
|
456 return;
|
rlm@1
|
457
|
rlm@1
|
458 // Test the cooperative level to see if it's okay to render
|
rlm@1
|
459 if (FAILED(pDevice->TestCooperativeLevel()))
|
rlm@1
|
460 {
|
rlm@1
|
461 return;
|
rlm@1
|
462 }
|
rlm@1
|
463 pDevice->Clear(0L, NULL, D3DCLEAR_TARGET, 0x000000ff, 1.0f, 0L);
|
rlm@1
|
464
|
rlm@1
|
465 if (SUCCEEDED(pDevice->BeginScene()))
|
rlm@1
|
466 {
|
rlm@1
|
467 D3DLOCKED_RECT locked;
|
rlm@1
|
468 if (pTexture && SUCCEEDED(pTexture->LockRect(0, &locked, NULL, 0)))
|
rlm@1
|
469 {
|
rlm@1
|
470 if (theApp.filterFunction)
|
rlm@1
|
471 {
|
rlm@1
|
472 if (systemColorDepth == 16)
|
rlm@1
|
473 theApp.filterFunction(pix + theApp.filterWidth * 2 + 4,
|
rlm@1
|
474 theApp.filterWidth*2 + 4,
|
rlm@1
|
475 (u8 *)theApp.delta,
|
rlm@1
|
476 (u8 *)locked.pBits,
|
rlm@1
|
477 locked.Pitch,
|
rlm@1
|
478 theApp.filterWidth,
|
rlm@1
|
479 theApp.filterHeight);
|
rlm@1
|
480 else
|
rlm@1
|
481 theApp.filterFunction(pix + theApp.filterWidth * 4 + 4,
|
rlm@1
|
482 theApp.filterWidth * 4 + 4,
|
rlm@1
|
483 (u8 *)theApp.delta,
|
rlm@1
|
484 (u8 *)locked.pBits,
|
rlm@1
|
485 locked.Pitch,
|
rlm@1
|
486 theApp.filterWidth,
|
rlm@1
|
487 theApp.filterHeight);
|
rlm@1
|
488 }
|
rlm@1
|
489 else
|
rlm@1
|
490 {
|
rlm@1
|
491 int copyX = 240;
|
rlm@1
|
492 int copyY = 160;
|
rlm@1
|
493
|
rlm@1
|
494 if (systemCartridgeType == 1)
|
rlm@1
|
495 {
|
rlm@1
|
496 if (gbBorderOn)
|
rlm@1
|
497 {
|
rlm@1
|
498 copyX = 256;
|
rlm@1
|
499 copyY = 224;
|
rlm@1
|
500 }
|
rlm@1
|
501 else
|
rlm@1
|
502 {
|
rlm@1
|
503 copyX = 160;
|
rlm@1
|
504 copyY = 144;
|
rlm@1
|
505 }
|
rlm@1
|
506 }
|
rlm@1
|
507 // MMX doesn't seem to be faster to copy the data
|
rlm@1
|
508 __asm {
|
rlm@1
|
509 mov eax, copyX;
|
rlm@1
|
510 mov ebx, copyY;
|
rlm@1
|
511
|
rlm@1
|
512 mov esi, pix;
|
rlm@1
|
513 mov edi, locked.pBits;
|
rlm@1
|
514 mov edx, locked.Pitch;
|
rlm@1
|
515 cmp systemColorDepth, 16;
|
rlm@1
|
516 jnz gbaOtherColor;
|
rlm@1
|
517 sub edx, eax;
|
rlm@1
|
518 sub edx, eax;
|
rlm@1
|
519 lea esi, [esi+2*eax+4];
|
rlm@1
|
520 shr eax, 1;
|
rlm@1
|
521 gbaLoop16bit:
|
rlm@1
|
522 mov ecx, eax;
|
rlm@1
|
523 repz movsd;
|
rlm@1
|
524 inc esi;
|
rlm@1
|
525 inc esi;
|
rlm@1
|
526 inc esi;
|
rlm@1
|
527 inc esi;
|
rlm@1
|
528 add edi, edx;
|
rlm@1
|
529 dec ebx;
|
rlm@1
|
530 jnz gbaLoop16bit;
|
rlm@1
|
531 jmp gbaLoopEnd;
|
rlm@1
|
532 gbaOtherColor:
|
rlm@1
|
533 cmp systemColorDepth, 32;
|
rlm@1
|
534 jnz gbaOtherColor2;
|
rlm@1
|
535
|
rlm@1
|
536 sub edx, eax;
|
rlm@1
|
537 sub edx, eax;
|
rlm@1
|
538 sub edx, eax;
|
rlm@1
|
539 sub edx, eax;
|
rlm@1
|
540 lea esi, [esi+4*eax+4];
|
rlm@1
|
541 gbaLoop32bit:
|
rlm@1
|
542 mov ecx, eax;
|
rlm@1
|
543 repz movsd;
|
rlm@1
|
544 add esi, 4;
|
rlm@1
|
545 add edi, edx;
|
rlm@1
|
546 dec ebx;
|
rlm@1
|
547 jnz gbaLoop32bit;
|
rlm@1
|
548 jmp gbaLoopEnd;
|
rlm@1
|
549 gbaOtherColor2:
|
rlm@1
|
550 lea eax, [eax+2*eax];
|
rlm@1
|
551 sub edx, eax;
|
rlm@1
|
552 gbaLoop24bit:
|
rlm@1
|
553 mov ecx, eax;
|
rlm@1
|
554 shr ecx, 2;
|
rlm@1
|
555 repz movsd;
|
rlm@1
|
556 add edi, edx;
|
rlm@1
|
557 dec ebx;
|
rlm@1
|
558 jnz gbaLoop24bit;
|
rlm@1
|
559 gbaLoopEnd:
|
rlm@1
|
560 }
|
rlm@1
|
561 }
|
rlm@1
|
562
|
rlm@1
|
563 if (theApp.videoOption > VIDEO_4X && theApp.showSpeed)
|
rlm@1
|
564 {
|
rlm@1
|
565 char buffer[30];
|
rlm@1
|
566 if (theApp.showSpeed == 1)
|
rlm@1
|
567 sprintf(buffer, "%3d%%", systemSpeed);
|
rlm@1
|
568 else
|
rlm@1
|
569 sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
|
rlm@1
|
570 systemFrameSkip,
|
rlm@1
|
571 theApp.showRenderedFrames);
|
rlm@1
|
572 if (theApp.showSpeedTransparent)
|
rlm@1
|
573 drawTextTransp((u8 *)locked.pBits,
|
rlm@1
|
574 locked.Pitch,
|
rlm@1
|
575 theApp.rect.left+10,
|
rlm@1
|
576 theApp.rect.bottom-10,
|
rlm@1
|
577 buffer);
|
rlm@1
|
578 else
|
rlm@1
|
579 drawText((u8 *)locked.pBits,
|
rlm@1
|
580 locked.Pitch,
|
rlm@1
|
581 theApp.rect.left+10,
|
rlm@1
|
582 theApp.rect.bottom-10,
|
rlm@1
|
583 buffer);
|
rlm@1
|
584 }
|
rlm@1
|
585
|
rlm@1
|
586 if (textMethod == 1)
|
rlm@1
|
587 {
|
rlm@1
|
588 DrawTextMessages((u8 *)locked.pBits, locked.Pitch, theApp.rect.left, theApp.rect.bottom);
|
rlm@1
|
589 }
|
rlm@1
|
590
|
rlm@1
|
591 pTexture->UnlockRect(0);
|
rlm@1
|
592
|
rlm@1
|
593 // set the texture
|
rlm@1
|
594 pDevice->SetTexture(0, pTexture);
|
rlm@1
|
595
|
rlm@1
|
596 // configure shader for vertex type
|
rlm@1
|
597 pDevice->SetVertexShader(D3DFVF_TLVERTEX);
|
rlm@1
|
598
|
rlm@1
|
599 #ifdef D3D_DRAW_SINGLE_RECTANGLE
|
rlm@1
|
600 // draw the rectangle
|
rlm@1
|
601 pDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(D3DTLVERTEX));
|
rlm@1
|
602 //#undef D3D_DRAW_RECT
|
rlm@1
|
603 #else
|
rlm@1
|
604 // draw the triangles
|
rlm@1
|
605 pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, verts, sizeof(D3DTLVERTEX));
|
rlm@1
|
606 #endif
|
rlm@1
|
607 }
|
rlm@1
|
608
|
rlm@1
|
609 if (textMethod == 2)
|
rlm@1
|
610 {
|
rlm@1
|
611 for (int slot = 0; slot < SCREEN_MESSAGE_SLOTS; slot++)
|
rlm@1
|
612 {
|
rlm@1
|
613 if (theApp.screenMessage[slot])
|
rlm@1
|
614 {
|
rlm@1
|
615 if ((theApp.screenMessageDuration[slot] < 0 ||
|
rlm@1
|
616 (int)(GetTickCount() - theApp.screenMessageTime[slot]) < theApp.screenMessageDuration[slot]) &&
|
rlm@1
|
617 (!theApp.disableStatusMessage || slot == 1 || slot == 2) && pFont)
|
rlm@1
|
618 {
|
rlm@1
|
619 pFont->Begin();
|
rlm@1
|
620 RECT r;
|
rlm@1
|
621 D3DCOLOR color;
|
rlm@1
|
622
|
rlm@1
|
623 r.left = 10;
|
rlm@1
|
624 r.top = dpp.BackBufferHeight - 20*(slot+1);
|
rlm@1
|
625 r.right = dpp.BackBufferWidth - 10;
|
rlm@1
|
626 r.bottom = r.top + 20;
|
rlm@1
|
627
|
rlm@1
|
628 if (outlinedText)
|
rlm@1
|
629 {
|
rlm@1
|
630 color = textColor != 7 ? D3DCOLOR_ARGB(255, 0, 0, 0) : D3DCOLOR_ARGB(255, 255, 255, 255);
|
rlm@1
|
631
|
rlm@1
|
632 // draw outline
|
rlm@1
|
633 const static int xd [8] = {-1, 0, 1, 1, 1, 0, -1, -1};
|
rlm@1
|
634 const static int yd [8] = {-1, -1, -1, 0, 1, 1, 1, 0};
|
rlm@1
|
635 for (int i = 0; i < 8; i++)
|
rlm@1
|
636 {
|
rlm@1
|
637 RECT r2 = r;
|
rlm@1
|
638 r2.left += xd[i]; r2.right += xd[i];
|
rlm@1
|
639 r2.top += yd[i]; r2.bottom += yd[i];
|
rlm@1
|
640
|
rlm@1
|
641 pFont->DrawText(theApp.screenMessageBuffer[slot], -1, &r2, 0, color);
|
rlm@1
|
642 }
|
rlm@1
|
643 }
|
rlm@1
|
644
|
rlm@1
|
645 // draw center text
|
rlm@1
|
646 switch (textColor)
|
rlm@1
|
647 {
|
rlm@1
|
648 case 0:
|
rlm@1
|
649 color = D3DCOLOR_ARGB(255, 255, 255, 255); break;
|
rlm@1
|
650 case 1:
|
rlm@1
|
651 color = D3DCOLOR_ARGB(255, 255, 0, 0); break;
|
rlm@1
|
652 case 2:
|
rlm@1
|
653 color = D3DCOLOR_ARGB(255, 255, 255, 0); break;
|
rlm@1
|
654 case 3:
|
rlm@1
|
655 color = D3DCOLOR_ARGB(255, 0, 255, 0); break;
|
rlm@1
|
656 case 4:
|
rlm@1
|
657 color = D3DCOLOR_ARGB(255, 0, 255, 255); break;
|
rlm@1
|
658 case 5:
|
rlm@1
|
659 color = D3DCOLOR_ARGB(255, 0, 0, 255); break;
|
rlm@1
|
660 case 6:
|
rlm@1
|
661 color = D3DCOLOR_ARGB(255, 255, 0, 255); break;
|
rlm@1
|
662 case 7:
|
rlm@1
|
663 color = D3DCOLOR_ARGB(255, 0, 0, 0); break;
|
rlm@1
|
664 }
|
rlm@1
|
665 pFont->DrawText(theApp.screenMessageBuffer[slot], -1, &r, 0, color);
|
rlm@1
|
666
|
rlm@1
|
667 pFont->End();
|
rlm@1
|
668 }
|
rlm@1
|
669 else
|
rlm@1
|
670 {
|
rlm@1
|
671 theApp.screenMessage[slot] = false;
|
rlm@1
|
672 }
|
rlm@1
|
673 }
|
rlm@1
|
674 }
|
rlm@1
|
675 }
|
rlm@1
|
676
|
rlm@1
|
677 pDevice->EndScene();
|
rlm@1
|
678
|
rlm@1
|
679 pDevice->Present(NULL, NULL, NULL, NULL);
|
rlm@1
|
680 }
|
rlm@1
|
681 }
|
rlm@1
|
682
|
rlm@1
|
683 void Direct3DDisplay::invalidateDeviceObjects()
|
rlm@1
|
684 {
|
rlm@1
|
685 if (pFont)
|
rlm@1
|
686 pFont->Release();
|
rlm@1
|
687 pFont = NULL;
|
rlm@1
|
688 }
|
rlm@1
|
689
|
rlm@1
|
690 void Direct3DDisplay::resize(int w, int h)
|
rlm@1
|
691 {
|
rlm@1
|
692 if (pDevice && w > 0 && h > 0)
|
rlm@1
|
693 {
|
rlm@1
|
694 dpp.BackBufferWidth = w;
|
rlm@1
|
695 dpp.BackBufferHeight = h;
|
rlm@1
|
696 HRESULT hr;
|
rlm@1
|
697 invalidateDeviceObjects();
|
rlm@1
|
698 if (SUCCEEDED(hr = pDevice->Reset(&dpp)))
|
rlm@1
|
699 {
|
rlm@1
|
700 restoreDeviceObjects();
|
rlm@1
|
701 }
|
rlm@1
|
702 else
|
rlm@1
|
703 systemMessage(0, "Failed device reset %08x", hr);
|
rlm@1
|
704 }
|
rlm@1
|
705 calculateVertices();
|
rlm@1
|
706 }
|
rlm@1
|
707
|
rlm@1
|
708 bool Direct3DDisplay::changeRenderSize(int w, int h)
|
rlm@1
|
709 {
|
rlm@1
|
710 if (w != width || h != height)
|
rlm@1
|
711 {
|
rlm@1
|
712 if (pTexture)
|
rlm@1
|
713 {
|
rlm@1
|
714 pTexture->Release();
|
rlm@1
|
715 pTexture = NULL;
|
rlm@1
|
716 }
|
rlm@1
|
717 if (!initializeOffscreen(w, h))
|
rlm@1
|
718 {
|
rlm@1
|
719 failed = true;
|
rlm@1
|
720 return false;
|
rlm@1
|
721 }
|
rlm@1
|
722 }
|
rlm@1
|
723 calculateVertices();
|
rlm@1
|
724
|
rlm@1
|
725 return true;
|
rlm@1
|
726 }
|
rlm@1
|
727
|
rlm@1
|
728 void Direct3DDisplay::setOption(const char *option, int value)
|
rlm@1
|
729 {
|
rlm@1
|
730 if (!strcmp(option, "d3dFilter"))
|
rlm@1
|
731 updateFiltering(value);
|
rlm@1
|
732 }
|
rlm@1
|
733
|
rlm@1
|
734 int Direct3DDisplay::selectFullScreenMode(GUID * *)
|
rlm@1
|
735 {
|
rlm@1
|
736 HWND wnd = GetDesktopWindow();
|
rlm@1
|
737 RECT r;
|
rlm@1
|
738 GetWindowRect(wnd, &r);
|
rlm@1
|
739 int w = (r.right - r.left) & 4095;
|
rlm@1
|
740 int h = (r.bottom - r.top) & 4095;
|
rlm@1
|
741 HDC dc = GetDC(wnd);
|
rlm@1
|
742 int c = GetDeviceCaps(dc, BITSPIXEL);
|
rlm@1
|
743 ReleaseDC(wnd, dc);
|
rlm@1
|
744
|
rlm@1
|
745 return (c << 24) | (w << 12) | h;
|
rlm@1
|
746 }
|
rlm@1
|
747
|
rlm@1
|
748 IDisplay *newDirect3DDisplay()
|
rlm@1
|
749 {
|
rlm@1
|
750 return new Direct3DDisplay();
|
rlm@1
|
751 }
|
rlm@1
|
752
|