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