the old-new win32 port
[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
efcba75f 308#define PI 3.14159265f\r
309\r
cc68a136 310static int MakeVertexList()\r
311{\r
312 struct CustomVertex *vert=NULL,*pv=NULL;\r
313 float dist=0.0f;\r
314 float scalex=0.0f,scaley=0.0f;\r
315 unsigned int colour=0xffffff;\r
316 float right=0.0f,bottom=0.0f;\r
317\r
318 if (LoopMode!=8) colour=0x102040;\r
319\r
320 dist=10.0f; scalex=dist*1.3333f; scaley=dist;\r
321\r
322 scalex*=640.0f/(float)MainWidth;\r
323 scaley*=448.0f/(float)MainHeight;\r
324\r
325 vert=VertexList;\r
326\r
327 // Put the vertices for the corners of the screen:\r
328 pv=vert;\r
329 pv->z=dist;\r
330 pv->x=-scalex; pv->y=scaley;\r
331 pv->colour=colour; pv++;\r
332\r
333 *pv=vert[0]; pv->x= scalex; pv->y= scaley; pv++;\r
334 *pv=vert[0]; pv->x=-scalex; pv->y=-scaley; pv++;\r
335 *pv=vert[0]; pv->x= scalex; pv->y=-scaley; pv++;\r
336\r
337 // Find where the screen images ends on the texture\r
338 right =(float)EmuWidth /(float)TexWidth;\r
339 bottom=(float)EmuHeight/(float)TexHeight;\r
340\r
341 // Write texture coordinates:\r
342 pv=vert;\r
343 pv->u=0.0f; pv->v=0.00f; pv++;\r
344 pv->u=right; pv->v=0.00f; pv++;\r
345 pv->u=0.0f; pv->v=bottom; pv++;\r
346 pv->u=right; pv->v=bottom; pv++;\r
347\r
348 return 0;\r
349}\r
350\r
cc68a136 351static int SetupMatrices()\r
352{\r
353 D3DXVECTOR3 eye ( 0.0f, 0.0f, 0.0f );\r
354 D3DXVECTOR3 look( 0.0f, 0.0f, 0.0f );\r
355 D3DXVECTOR3 up ( 0.0f, 1.0f, 0.0f );\r
356 D3DXMATRIX mat;\r
357 float nudgex=0.0f,nudgey=0.0f;\r
358\r
359 memset(&mat,0,sizeof(mat));\r
03a265e5 360\r
cc68a136 361 mat.m[0][0]=mat.m[1][1]=mat.m[2][2]=mat.m[3][3]=1.0f;\r
362 Device->SetTransform(D3DTS_WORLD,&mat);\r
363\r
364 look.x=(float)Inp.axis[2]/2457.6f;\r
365 look.y=(float)Inp.axis[3]/2457.6f;\r
366 look.z=10.0f;\r
367\r
368 // Nudge pixels to the centre of each screen pixel:\r
369 nudgex=13.3333f/(float)(MainWidth <<1);\r
370 nudgey=10.0000f/(float)(MainHeight<<1);\r
371 eye.x +=nudgex; eye.y +=nudgey;\r
372 look.x+=nudgex; look.y+=nudgey;\r
373\r
374 D3DXMatrixLookAtLH(&mat,&eye,&look,&up);\r
375 Device->SetTransform(D3DTS_VIEW,&mat);\r
376\r
377 D3DXMatrixPerspectiveFovLH(&mat, 0.5f*PI, 1.3333f, 0.2f, 1000.0f);\r
378 Device->SetTransform(D3DTS_PROJECTION,&mat);\r
379 return 0;\r
380}\r
381\r
382int DirectScreen()\r
383{\r
384 unsigned char *lock=NULL;\r
8831ef19 385 int ret;\r
cc68a136 386\r
03a265e5 387 if (Device == NULL)\r
388 return DirectScreenDDraw();\r
389\r
cc68a136 390 // Copy the screen to the screen texture:\r
391#ifdef _XBOX\r
392 TexScreenSwizzle();\r
393#else\r
8831ef19 394 ret=TexScreenLinear();\r
8f7ed1b8 395 if (ret) lprintf("TexScreenLinear failed\n");\r
cc68a136 396#endif\r
397\r
398 SetupMatrices();\r
399\r
400 MakeVertexList();\r
401\r
402 // Copy vertices in:\r
8831ef19 403 VertexBuffer->Lock(0,sizeof(VertexList),&lock,0);\r
8f7ed1b8 404 if (lock==NULL) { lprintf("VertexBuffer->Lock failed\n"); return 1; }\r
cc68a136 405 memcpy(lock,VertexList,sizeof(VertexList));\r
406 VertexBuffer->Unlock();\r
407\r
03a265e5 408 Device->BeginScene();\r
409 Device->SetTexture(0,TexScreen);\r
410 Device->SetStreamSource(0,VertexBuffer,sizeof(CustomVertex));\r
411 Device->SetVertexShader(D3DFVF_CUSTOMVERTEX);\r
412 Device->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2);\r
413 Device->EndScene();\r
8831ef19 414\r
cc68a136 415 return 0;\r
416}\r
1b0ac8ad 417#else\r
418int DirectScreen()\r
419{\r
420 return DirectScreenDDraw();\r
421}\r
422#endif\r
423\r