minor game_def.cfg update
[picodrive.git] / platform / win32 / GenaDrive / Direct.cpp
CommitLineData
cc68a136 1#include "app.h"\r
2\r
1b0ac8ad 3#ifdef USE_D3D\r
7c9e6899 4// d3d\r
cc68a136 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
1b0ac8ad 20#endif\r
cc68a136 21\r
7c9e6899 22// ddraw\r
23#include <ddraw.h>\r
24\r
03a265e5 25LPDIRECTDRAW7 m_pDD = NULL;\r
26LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer = NULL;\r
27LPDIRECTDRAWSURFACE7 m_pddsBackBuffer = NULL;\r
7c9e6899 28\r
29// quick and dirty stuff..\r
03a265e5 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
7c9e6899 37static int DirectDrawInit()\r
38{\r
39 HRESULT ret;\r
03a265e5 40 LPDIRECTDRAWCLIPPER pcClipper = NULL;\r
41 DDSURFACEDESC2 ddsd;\r
7c9e6899 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
03a265e5 48 if (ret) { LOGFAIL(); goto fail; }\r
7c9e6899 49\r
50 // Create the primary surface\r
7c9e6899 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
03a265e5 57 if (ret) { LOGFAIL(); goto fail; }\r
7c9e6899 58\r
59 // Create the backbuffer surface\r
03a265e5 60 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;\r
278922b8 61 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;\r
03a265e5 62 ddsd.dwWidth = EmuWidth;\r
63 ddsd.dwHeight = EmuHeight;\r
7c9e6899 64\r
65 ret = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL );\r
03a265e5 66 if (ret) { LOGFAIL(); goto fail; }\r
7c9e6899 67\r
68 // clipper\r
7c9e6899 69 ret = m_pDD->CreateClipper( 0, &pcClipper, NULL );\r
03a265e5 70 if (ret) { LOGFAIL(); goto fail; }\r
7c9e6899 71\r
72 ret = pcClipper->SetHWnd( 0, FrameWnd );\r
03a265e5 73 if (ret) { LOGFAIL(); goto fail; }\r
7c9e6899 74\r
75 ret = m_pddsFrontBuffer->SetClipper( pcClipper );\r
03a265e5 76 if (ret) { LOGFAIL(); goto fail; }\r
7c9e6899 77\r
78 RELEASE(pcClipper);\r
03a265e5 79 return 0;\r
7c9e6899 80\r
03a265e5 81fail:\r
82 RELEASE(pcClipper);\r
83 DirectExitDDraw();\r
84 return 1;\r
85}\r
86\r
87static int DirectScreenDDraw()\r
88{\r
7c9e6899 89 DDSURFACEDESC2 sd;\r
03a265e5 90 unsigned short *ps=EmuScreen;\r
91 int ret, x, y;\r
92\r
7c9e6899 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
8f7ed1b8 98 //lprintf("w: %i h: %i pi: %i pf: %i\n", sd.dwWidth, sd.dwHeight, sd.lPitch, sd.ddpfPixelFormat.dwRGBBitCount);\r
03a265e5 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
278922b8 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
03a265e5 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
7c9e6899 141\r
142 ret = m_pddsBackBuffer->Unlock(NULL);\r
143 if (ret) { LOGFAIL(); return 1; }\r
03a265e5 144 return 0;\r
145}\r
7c9e6899 146\r
03a265e5 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
7c9e6899 154\r
03a265e5 155 if (m_pddsBackBuffer != NULL)\r
156 ret = m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx );\r
7c9e6899 157 if (ret) { LOGFAIL(); return 1; }\r
03a265e5 158 return 0;\r
159}\r
160\r
161static int DirectPresentDDraw()\r
162{\r
2cb51c3c 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
7c9e6899 166 if (ret) { LOGFAIL(); return 1; }\r
7c9e6899 167 return 0;\r
168}\r
169\r
170\r
03a265e5 171/* D3D */\r
172\r
cc68a136 173int DirectInit()\r
174{\r
1b0ac8ad 175#if USE_D3D\r
03a265e5 176 D3DPRESENT_PARAMETERS d3dpp;\r
cc68a136 177 D3DDISPLAYMODE mode;\r
8831ef19 178 int i,u,ret=0;\r
cc68a136 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
03a265e5 190 d3dpp.MultiSampleType =D3DMULTISAMPLE_NONE;\r
cc68a136 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
03a265e5 199 d3dpp.hDeviceWindow=FrameWnd;\r
cc68a136 200#endif\r
201\r
202 // Try to create a device with hardware vertex processing:\r
7c9e6899 203 for (i=0;i<3;i++)\r
cc68a136 204 {\r
7c9e6899 205 int behave=D3DCREATE_HARDWARE_VERTEXPROCESSING;\r
cc68a136 206\r
7c9e6899 207 // Try software vertex processing:\r
208 if (i==1) behave=D3DCREATE_MIXED_VERTEXPROCESSING;\r
209 if (i==2) behave=D3DCREATE_SOFTWARE_VERTEXPROCESSING;\r
cc68a136 210\r
7c9e6899 211 Direct3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,FrameWnd,\r
212 behave|D3DCREATE_MULTITHREADED,&d3dpp,&Device);\r
cc68a136 213 if (Device) break;\r
214 }\r
215\r
7c9e6899 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
cc68a136 235\r
236 Device->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&DirectBack);\r
7c9e6899 237 if (DirectBack==NULL) goto fail1;\r
cc68a136 238\r
239 Device->CreateVertexBuffer(sizeof(VertexList),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT,&VertexBuffer);\r
7c9e6899 240 if (VertexBuffer==NULL) goto fail2;\r
cc68a136 241\r
7c9e6899 242 ret=TexScreenInit(); if (ret) goto fail3;\r
cc68a136 243\r
4b2b67eb 244 //FontInit();\r
cc68a136 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
7c9e6899 251\r
cc68a136 252 return 0;\r
7c9e6899 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
1b0ac8ad 264#endif\r
7c9e6899 265 // try DirectDraw\r
266 return DirectDrawInit();\r
cc68a136 267}\r
268\r
269void DirectExit()\r
270{\r
1b0ac8ad 271#ifdef USE_D3D\r
7c9e6899 272 TexScreenExit();\r
cc68a136 273\r
03a265e5 274 // d3d\r
cc68a136 275 RELEASE(VertexBuffer)\r
276 RELEASE(DirectBack)\r
277 RELEASE(Device)\r
278 RELEASE(Direct3D)\r
1b0ac8ad 279#endif\r
03a265e5 280 DirectExitDDraw();\r
cc68a136 281}\r
282\r
1b0ac8ad 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
cc68a136 291\r
1b0ac8ad 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
cc68a136 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
cc68a136 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
03a265e5 358\r
cc68a136 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
8831ef19 383 int ret;\r
cc68a136 384\r
03a265e5 385 if (Device == NULL)\r
386 return DirectScreenDDraw();\r
387\r
cc68a136 388 // Copy the screen to the screen texture:\r
389#ifdef _XBOX\r
390 TexScreenSwizzle();\r
391#else\r
8831ef19 392 ret=TexScreenLinear();\r
8f7ed1b8 393 if (ret) lprintf("TexScreenLinear failed\n");\r
cc68a136 394#endif\r
395\r
396 SetupMatrices();\r
397\r
398 MakeVertexList();\r
399\r
400 // Copy vertices in:\r
8831ef19 401 VertexBuffer->Lock(0,sizeof(VertexList),&lock,0);\r
8f7ed1b8 402 if (lock==NULL) { lprintf("VertexBuffer->Lock failed\n"); return 1; }\r
cc68a136 403 memcpy(lock,VertexList,sizeof(VertexList));\r
404 VertexBuffer->Unlock();\r
405\r
03a265e5 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
8831ef19 412\r
cc68a136 413 return 0;\r
414}\r
1b0ac8ad 415#else\r
416int DirectScreen()\r
417{\r
418 return DirectScreenDDraw();\r
419}\r
420#endif\r
421\r