win32 Pico mostly finished
[picodrive.git] / platform / win32 / GenaDrive / Direct.cpp
... / ...
CommitLineData
1#include "app.h"\r
2\r
3#ifdef USE_D3D\r
4// d3d\r
5static IDirect3D8 *Direct3D=NULL;\r
6IDirect3DDevice8 *Device=NULL;\r
7IDirect3DSurface8 *DirectBack=NULL; // Back Buffer\r
8\r
9static IDirect3DVertexBuffer8 *VertexBuffer=NULL;\r
10\r
11struct CustomVertex\r
12{\r
13 float x,y,z; // Vertex cordinates\r
14 unsigned int colour;\r
15 float u,v; // Texture coordinates\r
16};\r
17#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)\r
18\r
19static CustomVertex VertexList[4];\r
20#endif\r
21\r
22// ddraw\r
23#include <ddraw.h>\r
24\r
25LPDIRECTDRAW7 m_pDD = NULL;\r
26LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer = NULL;\r
27LPDIRECTDRAWSURFACE7 m_pddsBackBuffer = NULL;\r
28\r
29// quick and dirty stuff..\r
30static void DirectExitDDraw()\r
31{\r
32 RELEASE(m_pddsBackBuffer);\r
33 RELEASE(m_pddsFrontBuffer);\r
34 RELEASE(m_pDD);\r
35}\r
36\r
37static int DirectDrawInit()\r
38{\r
39 HRESULT ret;\r
40 LPDIRECTDRAWCLIPPER pcClipper = NULL;\r
41 DDSURFACEDESC2 ddsd;\r
42\r
43 ret = DirectDrawCreateEx(NULL, (VOID**)&m_pDD, IID_IDirectDraw7, NULL);\r
44 if (ret) { LOGFAIL(); return 1; }\r
45\r
46 // Set cooperative level\r
47 ret = m_pDD->SetCooperativeLevel( FrameWnd, DDSCL_NORMAL );\r
48 if (ret) { LOGFAIL(); goto fail; }\r
49\r
50 // Create the primary surface\r
51 ZeroMemory( &ddsd, sizeof( ddsd ) );\r
52 ddsd.dwSize = sizeof( ddsd );\r
53 ddsd.dwFlags = DDSD_CAPS;\r
54 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;\r
55\r
56 ret = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL );\r
57 if (ret) { LOGFAIL(); goto fail; }\r
58\r
59 // Create the backbuffer surface\r
60 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;\r
61 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;\r
62 ddsd.dwWidth = EmuWidth;\r
63 ddsd.dwHeight = EmuHeight;\r
64\r
65 ret = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL );\r
66 if (ret) { LOGFAIL(); goto fail; }\r
67\r
68 // clipper\r
69 ret = m_pDD->CreateClipper( 0, &pcClipper, NULL );\r
70 if (ret) { LOGFAIL(); goto fail; }\r
71\r
72 ret = pcClipper->SetHWnd( 0, FrameWnd );\r
73 if (ret) { LOGFAIL(); goto fail; }\r
74\r
75 ret = m_pddsFrontBuffer->SetClipper( pcClipper );\r
76 if (ret) { LOGFAIL(); goto fail; }\r
77\r
78 RELEASE(pcClipper);\r
79 return 0;\r
80\r
81fail:\r
82 RELEASE(pcClipper);\r
83 DirectExitDDraw();\r
84 return 1;\r
85}\r
86\r
87static int DirectScreenDDraw()\r
88{\r
89 DDSURFACEDESC2 sd;\r
90 unsigned short *ps=EmuScreen;\r
91 int ret, x, y;\r
92\r
93 memset(&sd, 0, sizeof(sd));\r
94 sd.dwSize = sizeof(sd);\r
95 ret = m_pddsBackBuffer->Lock(NULL, &sd, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_WRITEONLY, NULL);\r
96 if (ret) { LOGFAIL(); return 1; }\r
97\r
98 //lprintf("w: %i h: %i pi: %i pf: %i\n", sd.dwWidth, sd.dwHeight, sd.lPitch, sd.ddpfPixelFormat.dwRGBBitCount);\r
99\r
100 if (sd.ddpfPixelFormat.dwRGBBitCount == 32)\r
101 {\r
102 int *dst = (int *)sd.lpSurface;\r
103 for (y = 0; y < EmuHeight; y++)\r
104 {\r
105 for (x = 0; x < EmuWidth; x++)\r
106 {\r
107 int s = *ps++;\r
108 dst[x] = ((s&0xf800)<<8) | ((s&0x07e0)<<5) | ((s&0x001f)<<3);\r
109 }\r
110 dst = (int *)((char *)dst + sd.lPitch);\r
111 }\r
112 }\r
113 else if (sd.ddpfPixelFormat.dwRGBBitCount == 24) /* wine uses this for me */\r
114 {\r
115 void *dst = sd.lpSurface;\r
116 for (y = 0; y < EmuHeight; y++)\r
117 {\r
118 unsigned char *dst1 = (unsigned char *) dst;\r
119 for (x = 0; x < EmuWidth; x++, dst1 += 3)\r
120 {\r
121 int s = *ps++;\r
122 dst1[2] = (s&0xf800)>>8; dst1[1] = (s&0x07e0)>>3; dst1[0] = s<<3; // BGR\r
123 }\r
124 dst = (void *)((char *)dst + sd.lPitch);\r
125 }\r
126 }\r
127 else if (sd.ddpfPixelFormat.dwRGBBitCount == 16)\r
128 {\r
129 unsigned short *dst = (unsigned short *)sd.lpSurface;\r
130 for (y = 0; y < EmuHeight; y++)\r
131 {\r
132 memcpy(dst, ps, EmuWidth*2);\r
133 ps += EmuWidth;\r
134 dst = (unsigned short *)((char *)dst + sd.lPitch);\r
135 }\r
136 }\r
137 else\r
138 {\r
139 LOGFAIL();\r
140 }\r
141\r
142 ret = m_pddsBackBuffer->Unlock(NULL);\r
143 if (ret) { LOGFAIL(); return 1; }\r
144 return 0;\r
145}\r
146\r
147static int DirectClearDDraw(unsigned int colour)\r
148{\r
149 int ret;\r
150 DDBLTFX ddbltfx;\r
151 ZeroMemory( &ddbltfx, sizeof(ddbltfx) );\r
152 ddbltfx.dwSize = sizeof(ddbltfx);\r
153 ddbltfx.dwFillColor = colour;\r
154\r
155 if (m_pddsBackBuffer != NULL)\r
156 ret = m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx );\r
157 if (ret) { LOGFAIL(); return 1; }\r
158 return 0;\r
159}\r
160\r
161static int DirectPresentDDraw()\r
162{\r
163 int ret = 0;\r
164 if (FrameRectMy.right - FrameRectMy.left > 0 && FrameRectMy.bottom - FrameRectMy.top > 0)\r
165 ret = m_pddsFrontBuffer->Blt(&FrameRectMy, m_pddsBackBuffer, &EmuScreenRect, DDBLT_WAIT, NULL);\r
166 if (ret) { LOGFAIL(); return 1; }\r
167 return 0;\r
168}\r
169\r
170\r
171/* D3D */\r
172\r
173int DirectInit()\r
174{\r
175#if USE_D3D\r
176 D3DPRESENT_PARAMETERS d3dpp;\r
177 D3DDISPLAYMODE mode;\r
178 int i,u,ret=0;\r
179\r
180 memset(&d3dpp,0,sizeof(d3dpp));\r
181 memset(&mode,0,sizeof(mode));\r
182\r
183 Direct3D=Direct3DCreate8(D3D_SDK_VERSION); if (Direct3D==NULL) return 1;\r
184\r
185 // Set up the structure used to create the D3D device:\r
186 d3dpp.BackBufferWidth =MainWidth;\r
187 d3dpp.BackBufferHeight=MainHeight;\r
188 d3dpp.BackBufferCount =1;\r
189 d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;\r
190 d3dpp.MultiSampleType =D3DMULTISAMPLE_NONE;\r
191\r
192#ifdef _XBOX\r
193 d3dpp.BackBufferFormat=D3DFMT_X8R8G8B8;\r
194 d3dpp.FullScreen_RefreshRateInHz=60;\r
195#else\r
196 Direct3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&mode);\r
197 d3dpp.BackBufferFormat=mode.Format;\r
198 d3dpp.Windowed=1;\r
199 d3dpp.hDeviceWindow=FrameWnd;\r
200#endif\r
201\r
202 // Try to create a device with hardware vertex processing:\r
203 for (i=0;i<3;i++)\r
204 {\r
205 int behave=D3DCREATE_HARDWARE_VERTEXPROCESSING;\r
206\r
207 // Try software vertex processing:\r
208 if (i==1) behave=D3DCREATE_MIXED_VERTEXPROCESSING;\r
209 if (i==2) behave=D3DCREATE_SOFTWARE_VERTEXPROCESSING;\r
210\r
211 Direct3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,FrameWnd,\r
212 behave|D3DCREATE_MULTITHREADED,&d3dpp,&Device);\r
213 if (Device) break;\r
214 }\r
215\r
216 if (Device==NULL)\r
217 {\r
218#if 0\r
219 // try ref\r
220 Direct3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_REF,FrameWnd,\r
221 D3DCREATE_SOFTWARE_VERTEXPROCESSING|D3DCREATE_MULTITHREADED,&d3dpp,&Device);\r
222 if (Device==NULL) goto fail0;\r
223 HMODULE test = LoadLibrary("d3d8d.dll");\r
224 if (test != NULL) FreeLibrary(test);\r
225 else {\r
226 error("Sorry, but this program requires Direct3D with hardware acceleration.\n\n"\r
227 "You can try using Direct3D software emulation, but you have to install "\r
228 "DirectX SDK for it to work\n(it seems to be missing now).");\r
229 goto fail1;\r
230 }\r
231#else\r
232 goto fail1;\r
233#endif\r
234 }\r
235\r
236 Device->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&DirectBack);\r
237 if (DirectBack==NULL) goto fail1;\r
238\r
239 Device->CreateVertexBuffer(sizeof(VertexList),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT,&VertexBuffer);\r
240 if (VertexBuffer==NULL) goto fail2;\r
241\r
242 ret=TexScreenInit(); if (ret) goto fail3;\r
243\r
244 //FontInit();\r
245\r
246 Device->SetRenderState(D3DRS_LIGHTING,0); // Turn off lighting\r
247\r
248 // Set up texture modes:\r
249 Device->SetTextureStageState(0,D3DTSS_ADDRESSU,D3DTADDRESS_CLAMP);\r
250 Device->SetTextureStageState(0,D3DTSS_ADDRESSV,D3DTADDRESS_CLAMP);\r
251\r
252 return 0;\r
253\r
254fail3:\r
255 RELEASE(VertexBuffer)\r
256fail2:\r
257 RELEASE(DirectBack)\r
258fail1:\r
259 RELEASE(Device)\r
260fail0:\r
261 RELEASE(Direct3D)\r
262\r
263 // error("Failed to use Direct3D, trying DirectDraw..");\r
264#endif\r
265 // try DirectDraw\r
266 return DirectDrawInit();\r
267}\r
268\r
269void DirectExit()\r
270{\r
271#ifdef USE_D3D\r
272 TexScreenExit();\r
273\r
274 // d3d\r
275 RELEASE(VertexBuffer)\r
276 RELEASE(DirectBack)\r
277 RELEASE(Device)\r
278 RELEASE(Direct3D)\r
279#endif\r
280 DirectExitDDraw();\r
281}\r
282\r
283int DirectClear(unsigned int colour)\r
284{\r
285#ifdef USE_D3D\r
286 if (Device != NULL) {\r
287 Device->Clear(0,NULL,D3DCLEAR_TARGET,colour,1.0f,0);\r
288 return 0;\r
289 }\r
290#endif\r
291\r
292 return DirectClearDDraw(colour);\r
293}\r
294\r
295int DirectPresent()\r
296{\r
297#ifdef USE_D3D\r
298 if (Device != NULL) {\r
299 Device->Present(NULL,NULL,NULL,NULL);\r
300 return 0;\r
301 }\r
302#endif\r
303\r
304 return DirectPresentDDraw();\r
305}\r
306\r
307#ifdef USE_D3D\r
308static int MakeVertexList()\r
309{\r
310 struct CustomVertex *vert=NULL,*pv=NULL;\r
311 float dist=0.0f;\r
312 float scalex=0.0f,scaley=0.0f;\r
313 unsigned int colour=0xffffff;\r
314 float right=0.0f,bottom=0.0f;\r
315\r
316 if (LoopMode!=8) colour=0x102040;\r
317\r
318 dist=10.0f; scalex=dist*1.3333f; scaley=dist;\r
319\r
320 scalex*=640.0f/(float)MainWidth;\r
321 scaley*=448.0f/(float)MainHeight;\r
322\r
323 vert=VertexList;\r
324\r
325 // Put the vertices for the corners of the screen:\r
326 pv=vert;\r
327 pv->z=dist;\r
328 pv->x=-scalex; pv->y=scaley;\r
329 pv->colour=colour; pv++;\r
330\r
331 *pv=vert[0]; pv->x= scalex; pv->y= scaley; pv++;\r
332 *pv=vert[0]; pv->x=-scalex; pv->y=-scaley; pv++;\r
333 *pv=vert[0]; pv->x= scalex; pv->y=-scaley; pv++;\r
334\r
335 // Find where the screen images ends on the texture\r
336 right =(float)EmuWidth /(float)TexWidth;\r
337 bottom=(float)EmuHeight/(float)TexHeight;\r
338\r
339 // Write texture coordinates:\r
340 pv=vert;\r
341 pv->u=0.0f; pv->v=0.00f; pv++;\r
342 pv->u=right; pv->v=0.00f; pv++;\r
343 pv->u=0.0f; pv->v=bottom; pv++;\r
344 pv->u=right; pv->v=bottom; pv++;\r
345\r
346 return 0;\r
347}\r
348\r
349static int SetupMatrices()\r
350{\r
351 D3DXVECTOR3 eye ( 0.0f, 0.0f, 0.0f );\r
352 D3DXVECTOR3 look( 0.0f, 0.0f, 0.0f );\r
353 D3DXVECTOR3 up ( 0.0f, 1.0f, 0.0f );\r
354 D3DXMATRIX mat;\r
355 float nudgex=0.0f,nudgey=0.0f;\r
356\r
357 memset(&mat,0,sizeof(mat));\r
358\r
359 mat.m[0][0]=mat.m[1][1]=mat.m[2][2]=mat.m[3][3]=1.0f;\r
360 Device->SetTransform(D3DTS_WORLD,&mat);\r
361\r
362 look.x=(float)Inp.axis[2]/2457.6f;\r
363 look.y=(float)Inp.axis[3]/2457.6f;\r
364 look.z=10.0f;\r
365\r
366 // Nudge pixels to the centre of each screen pixel:\r
367 nudgex=13.3333f/(float)(MainWidth <<1);\r
368 nudgey=10.0000f/(float)(MainHeight<<1);\r
369 eye.x +=nudgex; eye.y +=nudgey;\r
370 look.x+=nudgex; look.y+=nudgey;\r
371\r
372 D3DXMatrixLookAtLH(&mat,&eye,&look,&up);\r
373 Device->SetTransform(D3DTS_VIEW,&mat);\r
374\r
375 D3DXMatrixPerspectiveFovLH(&mat, 0.5f*PI, 1.3333f, 0.2f, 1000.0f);\r
376 Device->SetTransform(D3DTS_PROJECTION,&mat);\r
377 return 0;\r
378}\r
379\r
380int DirectScreen()\r
381{\r
382 unsigned char *lock=NULL;\r
383 int ret;\r
384\r
385 if (Device == NULL)\r
386 return DirectScreenDDraw();\r
387\r
388 // Copy the screen to the screen texture:\r
389#ifdef _XBOX\r
390 TexScreenSwizzle();\r
391#else\r
392 ret=TexScreenLinear();\r
393 if (ret) lprintf("TexScreenLinear failed\n");\r
394#endif\r
395\r
396 SetupMatrices();\r
397\r
398 MakeVertexList();\r
399\r
400 // Copy vertices in:\r
401 VertexBuffer->Lock(0,sizeof(VertexList),&lock,0);\r
402 if (lock==NULL) { lprintf("VertexBuffer->Lock failed\n"); return 1; }\r
403 memcpy(lock,VertexList,sizeof(VertexList));\r
404 VertexBuffer->Unlock();\r
405\r
406 Device->BeginScene();\r
407 Device->SetTexture(0,TexScreen);\r
408 Device->SetStreamSource(0,VertexBuffer,sizeof(CustomVertex));\r
409 Device->SetVertexShader(D3DFVF_CUSTOMVERTEX);\r
410 Device->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2);\r
411 Device->EndScene();\r
412\r
413 return 0;\r
414}\r
415#else\r
416int DirectScreen()\r
417{\r
418 return DirectScreenDDraw();\r
419}\r
420#endif\r
421\r