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