bugfixes
[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
03a265e5 98 //dprintf2("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
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
1b0ac8ad 163 int ret = m_pddsFrontBuffer->Blt(&FrameRectMy, m_pddsBackBuffer, &EmuScreenRect, DDBLT_WAIT, NULL);\r
7c9e6899 164 if (ret) { LOGFAIL(); return 1; }\r
7c9e6899 165 return 0;\r
166}\r
167\r
168\r
03a265e5 169/* D3D */\r
170\r
cc68a136 171int DirectInit()\r
172{\r
1b0ac8ad 173#if USE_D3D\r
03a265e5 174 D3DPRESENT_PARAMETERS d3dpp;\r
cc68a136 175 D3DDISPLAYMODE mode;\r
8831ef19 176 int i,u,ret=0;\r
cc68a136 177\r
178 memset(&d3dpp,0,sizeof(d3dpp));\r
179 memset(&mode,0,sizeof(mode));\r
180\r
181 Direct3D=Direct3DCreate8(D3D_SDK_VERSION); if (Direct3D==NULL) return 1;\r
182\r
183 // Set up the structure used to create the D3D device:\r
184 d3dpp.BackBufferWidth =MainWidth;\r
185 d3dpp.BackBufferHeight=MainHeight;\r
186 d3dpp.BackBufferCount =1;\r
187 d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;\r
03a265e5 188 d3dpp.MultiSampleType =D3DMULTISAMPLE_NONE;\r
cc68a136 189\r
190#ifdef _XBOX\r
191 d3dpp.BackBufferFormat=D3DFMT_X8R8G8B8;\r
192 d3dpp.FullScreen_RefreshRateInHz=60;\r
193#else\r
194 Direct3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&mode);\r
195 d3dpp.BackBufferFormat=mode.Format;\r
196 d3dpp.Windowed=1;\r
03a265e5 197 d3dpp.hDeviceWindow=FrameWnd;\r
cc68a136 198#endif\r
199\r
200 // Try to create a device with hardware vertex processing:\r
7c9e6899 201 for (i=0;i<3;i++)\r
cc68a136 202 {\r
7c9e6899 203 int behave=D3DCREATE_HARDWARE_VERTEXPROCESSING;\r
cc68a136 204\r
7c9e6899 205 // Try software vertex processing:\r
206 if (i==1) behave=D3DCREATE_MIXED_VERTEXPROCESSING;\r
207 if (i==2) behave=D3DCREATE_SOFTWARE_VERTEXPROCESSING;\r
cc68a136 208\r
7c9e6899 209 Direct3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,FrameWnd,\r
210 behave|D3DCREATE_MULTITHREADED,&d3dpp,&Device);\r
cc68a136 211 if (Device) break;\r
212 }\r
213\r
7c9e6899 214 if (Device==NULL)\r
215 {\r
216#if 0\r
217 // try ref\r
218 Direct3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_REF,FrameWnd,\r
219 D3DCREATE_SOFTWARE_VERTEXPROCESSING|D3DCREATE_MULTITHREADED,&d3dpp,&Device);\r
220 if (Device==NULL) goto fail0;\r
221 HMODULE test = LoadLibrary("d3d8d.dll");\r
222 if (test != NULL) FreeLibrary(test);\r
223 else {\r
224 error("Sorry, but this program requires Direct3D with hardware acceleration.\n\n"\r
225 "You can try using Direct3D software emulation, but you have to install "\r
226 "DirectX SDK for it to work\n(it seems to be missing now).");\r
227 goto fail1;\r
228 }\r
229#else\r
230 goto fail1;\r
231#endif\r
232 }\r
cc68a136 233\r
234 Device->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&DirectBack);\r
7c9e6899 235 if (DirectBack==NULL) goto fail1;\r
cc68a136 236\r
237 Device->CreateVertexBuffer(sizeof(VertexList),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT,&VertexBuffer);\r
7c9e6899 238 if (VertexBuffer==NULL) goto fail2;\r
cc68a136 239\r
7c9e6899 240 ret=TexScreenInit(); if (ret) goto fail3;\r
cc68a136 241\r
4b2b67eb 242 //FontInit();\r
cc68a136 243\r
244 Device->SetRenderState(D3DRS_LIGHTING,0); // Turn off lighting\r
245\r
246 // Set up texture modes:\r
247 Device->SetTextureStageState(0,D3DTSS_ADDRESSU,D3DTADDRESS_CLAMP);\r
248 Device->SetTextureStageState(0,D3DTSS_ADDRESSV,D3DTADDRESS_CLAMP);\r
7c9e6899 249\r
cc68a136 250 return 0;\r
7c9e6899 251\r
252fail3:\r
253 RELEASE(VertexBuffer)\r
254fail2:\r
255 RELEASE(DirectBack)\r
256fail1:\r
257 RELEASE(Device)\r
258fail0:\r
259 RELEASE(Direct3D)\r
260\r
261 // error("Failed to use Direct3D, trying DirectDraw..");\r
1b0ac8ad 262#endif\r
7c9e6899 263 // try DirectDraw\r
264 return DirectDrawInit();\r
cc68a136 265}\r
266\r
267void DirectExit()\r
268{\r
1b0ac8ad 269#ifdef USE_D3D\r
7c9e6899 270 TexScreenExit();\r
cc68a136 271\r
03a265e5 272 // d3d\r
cc68a136 273 RELEASE(VertexBuffer)\r
274 RELEASE(DirectBack)\r
275 RELEASE(Device)\r
276 RELEASE(Direct3D)\r
1b0ac8ad 277#endif\r
03a265e5 278 DirectExitDDraw();\r
cc68a136 279}\r
280\r
1b0ac8ad 281int DirectClear(unsigned int colour)\r
282{\r
283#ifdef USE_D3D\r
284 if (Device != NULL) {\r
285 Device->Clear(0,NULL,D3DCLEAR_TARGET,colour,1.0f,0);\r
286 return 0;\r
287 }\r
288#endif\r
cc68a136 289\r
1b0ac8ad 290 return DirectClearDDraw(colour);\r
291}\r
292\r
293int DirectPresent()\r
294{\r
295#ifdef USE_D3D\r
296 if (Device != NULL) {\r
297 Device->Present(NULL,NULL,NULL,NULL);\r
298 return 0;\r
299 }\r
300#endif\r
301\r
302 return DirectPresentDDraw();\r
303}\r
304\r
305#ifdef USE_D3D\r
cc68a136 306static int MakeVertexList()\r
307{\r
308 struct CustomVertex *vert=NULL,*pv=NULL;\r
309 float dist=0.0f;\r
310 float scalex=0.0f,scaley=0.0f;\r
311 unsigned int colour=0xffffff;\r
312 float right=0.0f,bottom=0.0f;\r
313\r
314 if (LoopMode!=8) colour=0x102040;\r
315\r
316 dist=10.0f; scalex=dist*1.3333f; scaley=dist;\r
317\r
318 scalex*=640.0f/(float)MainWidth;\r
319 scaley*=448.0f/(float)MainHeight;\r
320\r
321 vert=VertexList;\r
322\r
323 // Put the vertices for the corners of the screen:\r
324 pv=vert;\r
325 pv->z=dist;\r
326 pv->x=-scalex; pv->y=scaley;\r
327 pv->colour=colour; pv++;\r
328\r
329 *pv=vert[0]; pv->x= scalex; pv->y= scaley; pv++;\r
330 *pv=vert[0]; pv->x=-scalex; pv->y=-scaley; pv++;\r
331 *pv=vert[0]; pv->x= scalex; pv->y=-scaley; pv++;\r
332\r
333 // Find where the screen images ends on the texture\r
334 right =(float)EmuWidth /(float)TexWidth;\r
335 bottom=(float)EmuHeight/(float)TexHeight;\r
336\r
337 // Write texture coordinates:\r
338 pv=vert;\r
339 pv->u=0.0f; pv->v=0.00f; pv++;\r
340 pv->u=right; pv->v=0.00f; pv++;\r
341 pv->u=0.0f; pv->v=bottom; pv++;\r
342 pv->u=right; pv->v=bottom; pv++;\r
343\r
344 return 0;\r
345}\r
346\r
cc68a136 347static int SetupMatrices()\r
348{\r
349 D3DXVECTOR3 eye ( 0.0f, 0.0f, 0.0f );\r
350 D3DXVECTOR3 look( 0.0f, 0.0f, 0.0f );\r
351 D3DXVECTOR3 up ( 0.0f, 1.0f, 0.0f );\r
352 D3DXMATRIX mat;\r
353 float nudgex=0.0f,nudgey=0.0f;\r
354\r
355 memset(&mat,0,sizeof(mat));\r
03a265e5 356\r
cc68a136 357 mat.m[0][0]=mat.m[1][1]=mat.m[2][2]=mat.m[3][3]=1.0f;\r
358 Device->SetTransform(D3DTS_WORLD,&mat);\r
359\r
360 look.x=(float)Inp.axis[2]/2457.6f;\r
361 look.y=(float)Inp.axis[3]/2457.6f;\r
362 look.z=10.0f;\r
363\r
364 // Nudge pixels to the centre of each screen pixel:\r
365 nudgex=13.3333f/(float)(MainWidth <<1);\r
366 nudgey=10.0000f/(float)(MainHeight<<1);\r
367 eye.x +=nudgex; eye.y +=nudgey;\r
368 look.x+=nudgex; look.y+=nudgey;\r
369\r
370 D3DXMatrixLookAtLH(&mat,&eye,&look,&up);\r
371 Device->SetTransform(D3DTS_VIEW,&mat);\r
372\r
373 D3DXMatrixPerspectiveFovLH(&mat, 0.5f*PI, 1.3333f, 0.2f, 1000.0f);\r
374 Device->SetTransform(D3DTS_PROJECTION,&mat);\r
375 return 0;\r
376}\r
377\r
378int DirectScreen()\r
379{\r
380 unsigned char *lock=NULL;\r
8831ef19 381 int ret;\r
cc68a136 382\r
03a265e5 383 if (Device == NULL)\r
384 return DirectScreenDDraw();\r
385\r
cc68a136 386 // Copy the screen to the screen texture:\r
387#ifdef _XBOX\r
388 TexScreenSwizzle();\r
389#else\r
8831ef19 390 ret=TexScreenLinear();\r
391 if (ret) dprintf2("TexScreenLinear failed\n");\r
cc68a136 392#endif\r
393\r
394 SetupMatrices();\r
395\r
396 MakeVertexList();\r
397\r
398 // Copy vertices in:\r
8831ef19 399 VertexBuffer->Lock(0,sizeof(VertexList),&lock,0);\r
400 if (lock==NULL) { dprintf2("VertexBuffer->Lock failed\n"); return 1; }\r
cc68a136 401 memcpy(lock,VertexList,sizeof(VertexList));\r
402 VertexBuffer->Unlock();\r
403\r
03a265e5 404 Device->BeginScene();\r
405 Device->SetTexture(0,TexScreen);\r
406 Device->SetStreamSource(0,VertexBuffer,sizeof(CustomVertex));\r
407 Device->SetVertexShader(D3DFVF_CUSTOMVERTEX);\r
408 Device->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2);\r
409 Device->EndScene();\r
8831ef19 410\r
cc68a136 411 return 0;\r
412}\r
1b0ac8ad 413#else\r
414int DirectScreen()\r
415{\r
416 return DirectScreenDDraw();\r
417}\r
418#endif\r
419\r