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