win32 stuff, SIMPLE_WRITE_SOUND
[picodrive.git] / platform / win32 / GenaDrive / Direct.cpp
CommitLineData
cc68a136 1#include "app.h"\r
2\r
7c9e6899 3// d3d\r
cc68a136 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
7c9e6899 20// ddraw\r
21#include <ddraw.h>\r
22\r
03a265e5 23LPDIRECTDRAW7 m_pDD = NULL;\r
24LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer = NULL;\r
25LPDIRECTDRAWSURFACE7 m_pddsBackBuffer = NULL;\r
7c9e6899 26\r
27// quick and dirty stuff..\r
03a265e5 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
7c9e6899 35static int DirectDrawInit()\r
36{\r
37 HRESULT ret;\r
03a265e5 38 LPDIRECTDRAWCLIPPER pcClipper = NULL;\r
39 DDSURFACEDESC2 ddsd;\r
7c9e6899 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
03a265e5 46 if (ret) { LOGFAIL(); goto fail; }\r
7c9e6899 47\r
48 // Create the primary surface\r
7c9e6899 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
03a265e5 55 if (ret) { LOGFAIL(); goto fail; }\r
7c9e6899 56\r
57 // Create the backbuffer surface\r
03a265e5 58 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;\r
7c9e6899 59 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;\r
03a265e5 60 ddsd.dwWidth = EmuWidth;\r
61 ddsd.dwHeight = EmuHeight;\r
7c9e6899 62\r
63 ret = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL );\r
03a265e5 64 if (ret) { LOGFAIL(); goto fail; }\r
7c9e6899 65\r
66 // clipper\r
7c9e6899 67 ret = m_pDD->CreateClipper( 0, &pcClipper, NULL );\r
03a265e5 68 if (ret) { LOGFAIL(); goto fail; }\r
7c9e6899 69\r
70 ret = pcClipper->SetHWnd( 0, FrameWnd );\r
03a265e5 71 if (ret) { LOGFAIL(); goto fail; }\r
7c9e6899 72\r
73 ret = m_pddsFrontBuffer->SetClipper( pcClipper );\r
03a265e5 74 if (ret) { LOGFAIL(); goto fail; }\r
7c9e6899 75\r
76 RELEASE(pcClipper);\r
03a265e5 77 return 0;\r
7c9e6899 78\r
03a265e5 79fail:\r
80 RELEASE(pcClipper);\r
81 DirectExitDDraw();\r
82 return 1;\r
83}\r
84\r
85static int DirectScreenDDraw()\r
86{\r
7c9e6899 87 DDSURFACEDESC2 sd;\r
03a265e5 88 unsigned short *ps=EmuScreen;\r
89 int ret, x, y;\r
90\r
7c9e6899 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
03a265e5 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
7c9e6899 125\r
126 ret = m_pddsBackBuffer->Unlock(NULL);\r
127 if (ret) { LOGFAIL(); return 1; }\r
03a265e5 128 return 0;\r
129}\r
7c9e6899 130\r
03a265e5 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
7c9e6899 138\r
03a265e5 139 if (m_pddsBackBuffer != NULL)\r
140 ret = m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx );\r
7c9e6899 141 if (ret) { LOGFAIL(); return 1; }\r
03a265e5 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
7c9e6899 148 if (ret) { LOGFAIL(); return 1; }\r
7c9e6899 149 return 0;\r
150}\r
151\r
152\r
03a265e5 153/* D3D */\r
154\r
cc68a136 155int DirectInit()\r
156{\r
03a265e5 157 D3DPRESENT_PARAMETERS d3dpp;\r
cc68a136 158 D3DDISPLAYMODE mode;\r
8831ef19 159 int i,u,ret=0;\r
cc68a136 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
03a265e5 171 d3dpp.MultiSampleType =D3DMULTISAMPLE_NONE;\r
cc68a136 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
03a265e5 180 d3dpp.hDeviceWindow=FrameWnd;\r
cc68a136 181#endif\r
182\r
183 // Try to create a device with hardware vertex processing:\r
7c9e6899 184 for (i=0;i<3;i++)\r
cc68a136 185 {\r
7c9e6899 186 int behave=D3DCREATE_HARDWARE_VERTEXPROCESSING;\r
cc68a136 187\r
7c9e6899 188 // Try software vertex processing:\r
189 if (i==1) behave=D3DCREATE_MIXED_VERTEXPROCESSING;\r
190 if (i==2) behave=D3DCREATE_SOFTWARE_VERTEXPROCESSING;\r
cc68a136 191\r
7c9e6899 192 Direct3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,FrameWnd,\r
193 behave|D3DCREATE_MULTITHREADED,&d3dpp,&Device);\r
cc68a136 194 if (Device) break;\r
195 }\r
196\r
7c9e6899 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
cc68a136 216\r
217 Device->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&DirectBack);\r
7c9e6899 218 if (DirectBack==NULL) goto fail1;\r
cc68a136 219\r
220 Device->CreateVertexBuffer(sizeof(VertexList),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT,&VertexBuffer);\r
7c9e6899 221 if (VertexBuffer==NULL) goto fail2;\r
cc68a136 222\r
7c9e6899 223 ret=TexScreenInit(); if (ret) goto fail3;\r
cc68a136 224\r
4b2b67eb 225 //FontInit();\r
cc68a136 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
7c9e6899 232\r
cc68a136 233 return 0;\r
7c9e6899 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
cc68a136 248}\r
249\r
250void DirectExit()\r
251{\r
4b2b67eb 252 //FontExit();\r
7c9e6899 253 TexScreenExit();\r
cc68a136 254\r
03a265e5 255 // d3d\r
cc68a136 256 RELEASE(VertexBuffer)\r
257 RELEASE(DirectBack)\r
258 RELEASE(Device)\r
259 RELEASE(Direct3D)\r
03a265e5 260\r
261 DirectExitDDraw();\r
cc68a136 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
03a265e5 308 if (Device == NULL)\r
309 return DirectClearDDraw(colour);\r
310\r
cc68a136 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
03a265e5 317 if (Device == NULL)\r
318 return DirectPresentDDraw();\r
319\r
cc68a136 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
03a265e5 333\r
cc68a136 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
8831ef19 358 int ret;\r
cc68a136 359\r
03a265e5 360 if (Device == NULL)\r
361 return DirectScreenDDraw();\r
362\r
cc68a136 363 // Copy the screen to the screen texture:\r
364#ifdef _XBOX\r
365 TexScreenSwizzle();\r
366#else\r
8831ef19 367 ret=TexScreenLinear();\r
368 if (ret) dprintf2("TexScreenLinear failed\n");\r
cc68a136 369#endif\r
370\r
371 SetupMatrices();\r
372\r
373 MakeVertexList();\r
374\r
375 // Copy vertices in:\r
8831ef19 376 VertexBuffer->Lock(0,sizeof(VertexList),&lock,0);\r
377 if (lock==NULL) { dprintf2("VertexBuffer->Lock failed\n"); return 1; }\r
cc68a136 378 memcpy(lock,VertexList,sizeof(VertexList));\r
379 VertexBuffer->Unlock();\r
380\r
03a265e5 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
8831ef19 387\r
cc68a136 388 return 0;\r
389}\r