1 /*
2   LICENSE
3   -------
4 Copyright 2005-2013 Nullsoft, Inc.
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without modification,
8 are permitted provided that the following conditions are met:
9 
10   * Redistributions of source code must retain the above copyright notice,
11     this list of conditions and the following disclaimer.
12 
13   * Redistributions in binary form must reproduce the above copyright notice,
14     this list of conditions and the following disclaimer in the documentation
15     and/or other materials provided with the distribution.
16 
17   * Neither the name of Nullsoft nor the names of its contributors may be used to
18     endorse or promote products derived from this software without specific prior written permission.
19 
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
21 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
27 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 #include "support.h"
31 #include "utility.h"
32 #include "../Winamp/wa_ipc.h"
33 
34 bool g_bDebugOutput = false;
35 bool g_bDumpFileCleared = false;
36 
37 //---------------------------------------------------
PrepareFor3DDrawing(IDirect3DDevice9 * pDevice,int viewport_width,int viewport_height,float fov_in_degrees,float near_clip,float far_clip,D3DXVECTOR3 * pvEye,D3DXVECTOR3 * pvLookat,D3DXVECTOR3 * pvUp)38 void PrepareFor3DDrawing(
39         IDirect3DDevice9 *pDevice,
40         int viewport_width,
41         int viewport_height,
42         float fov_in_degrees,
43         float near_clip,
44         float far_clip,
45         D3DXVECTOR3* pvEye,
46         D3DXVECTOR3* pvLookat,
47         D3DXVECTOR3* pvUp
48     )
49 {
50     // This function sets up DirectX up for 3D rendering.
51     // Only call it once per frame, as it is VERY slow.
52     // INPUTS:
53     //    pDevice           a pointer to the D3D device
54     //    viewport_width    the width of the client area of the window
55     //    viewport_height   the height of the client area of the window
56     //    fov_in_degrees    the field of view, in degrees
57     //    near_clip         the distance to the near clip plane; should be > 0!
58     //    far_clip          the distance to the far clip plane
59     //    eye               the eyepoint coordinates, in world space
60     //    lookat            the point toward which the eye is looking, in world space
61     //    up                a vector indicating which dir. is up; usually <0,1,0>
62     //
63     // What this function does NOT do:
64     //    1. set the current texture (SetTexture)
65     //    2. set up the texture stages for texturing (SetTextureStageState)
66     //    3. set the current vertex format (SetVertexShader)
67     //    4. set up the world matrix (SetTransform(D3DTS_WORLD, &my_world_matrix))
68 
69 
70     // set up render state to some nice defaults:
71     {
72         // some defaults
73         pDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
74         pDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
75         pDevice->SetRenderState( D3DRS_ZFUNC,     D3DCMP_LESSEQUAL );
76         pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
77         pDevice->SetRenderState( D3DRS_CLIPPING, TRUE );
78         pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
79         pDevice->SetRenderState( D3DRS_COLORVERTEX, TRUE );
80         pDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD );
81         pDevice->SetRenderState( D3DRS_FILLMODE,  D3DFILL_SOLID );
82         pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
83 
84         // turn fog off
85         pDevice->SetRenderState( D3DRS_FOGENABLE, FALSE );
86         pDevice->SetRenderState( D3DRS_RANGEFOGENABLE, FALSE );
87 
88         // turn on high-quality bilinear interpolations
89         pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
90         pDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
91         pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
92         pDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
93         pDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
94         pDevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
95     }
96 
97     // set up view & projection matrices (but not the world matrix!)
98     {
99         // if the window is not square, instead of distorting the scene,
100         // clip it so that the longer dimension of the window has the
101         // regular FOV, and the shorter dimension has a reduced FOV.
102         float fov_x = fov_in_degrees * 3.1415927f/180.0f;
103         float fov_y = fov_in_degrees * 3.1415927f/180.0f;
104         float aspect = (float)viewport_height / (float)viewport_width;
105         if (aspect < 1)
106             fov_y *= aspect;
107         else
108             fov_x /= aspect;
109 
110         if (near_clip < 0.1f)
111             near_clip = 0.1f;
112         if (far_clip < near_clip + 1.0f)
113             far_clip = near_clip + 1.0f;
114 
115         D3DXMATRIX proj;
116         MakeProjectionMatrix(&proj, near_clip, far_clip, fov_x, fov_y);
117         pDevice->SetTransform(D3DTS_PROJECTION, &proj);
118 
119         D3DXMATRIX view;
120         pMatrixLookAtLH(&view, pvEye, pvLookat, pvUp);
121         pDevice->SetTransform(D3DTS_VIEW, &view);
122 
123         // Optimization note: "You can minimize the number of required calculations
124         // by concatenating your world and view matrices into a world-view matrix
125         // that you set as the world matrix, and then setting the view matrix
126         // to the identity."
127         //D3DXMatrixMultiply(&world, &world, &view);
128         //D3DXMatrixIdentity(&view);
129     }
130 }
131 
PrepareFor2DDrawing(IDirect3DDevice9 * pDevice)132 void PrepareFor2DDrawing(IDirect3DDevice9 *pDevice)
133 {
134     // New 2D drawing area will have x,y coords in the range <-1,-1> .. <1,1>
135     //         +--------+ Y=-1
136     //         |        |
137     //         | screen |             Z=0: front of scene
138     //         |        |             Z=1: back of scene
139     //         +--------+ Y=1
140     //       X=-1      X=1
141     // NOTE: After calling this, be sure to then call (at least):
142     //  1. SetVertexShader()
143     //  2. SetTexture(), if you need it
144     // before rendering primitives!
145     // Also, be sure your sprites have a z coordinate of 0.
146     pDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
147     pDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
148     pDevice->SetRenderState( D3DRS_ZFUNC,     D3DCMP_LESSEQUAL );
149     pDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT );
150     pDevice->SetRenderState( D3DRS_FILLMODE,  D3DFILL_SOLID );
151     pDevice->SetRenderState( D3DRS_FOGENABLE, FALSE );
152     pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
153     pDevice->SetRenderState( D3DRS_CLIPPING, TRUE );
154     pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
155     pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
156     pDevice->SetRenderState( D3DRS_LOCALVIEWER, FALSE );
157 
158     pDevice->SetTexture(0, NULL);
159     pDevice->SetTexture(1, NULL);
160     pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);//D3DTEXF_LINEAR);
161     pDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_POINT);//D3DTEXF_LINEAR);
162     pDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
163     pDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
164     pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE );
165     pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
166     pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT );
167     pDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE );
168 
169     pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
170     pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
171     pDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
172 
173     pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
174 
175     // set up for 2D drawing:
176     {
177         D3DXMATRIX Ortho2D;
178         D3DXMATRIX Identity;
179 
180         pMatrixOrthoLH(&Ortho2D, 2.0f, -2.0f, 0.0f, 1.0f);
181         D3DXMatrixIdentity(&Identity);
182 
183         pDevice->SetTransform(D3DTS_PROJECTION, &Ortho2D);
184         pDevice->SetTransform(D3DTS_WORLD, &Identity);
185         pDevice->SetTransform(D3DTS_VIEW, &Identity);
186     }
187 }
188 
189 //---------------------------------------------------
190 
MakeWorldMatrix(D3DXMATRIX * pOut,float xpos,float ypos,float zpos,float sx,float sy,float sz,float pitch,float yaw,float roll)191 void MakeWorldMatrix( D3DXMATRIX* pOut,
192                       float xpos, float ypos, float zpos,
193                       float sx,   float sy,   float sz,
194                       float pitch, float yaw, float roll)
195 {
196     /*
197      * The m_xPos, m_yPos, m_zPos variables contain the model's
198      * location in world coordinates.
199      * The m_fPitch, m_fYaw, and m_fRoll variables are floats that
200      * contain the model's orientation in terms of pitch, yaw, and roll
201      * angles, in radians.
202      */
203 
204     D3DXMATRIX MatTemp;
205     D3DXMatrixIdentity(pOut);
206 
207     // 1. first, rotation
208     if (pitch || yaw || roll)
209     {
210         D3DXMATRIX MatRot;
211         D3DXMatrixIdentity(&MatRot);
212 
213         pMatrixRotationX(&MatTemp, pitch);         // Pitch
214         pMatrixMultiply(&MatRot, &MatRot, &MatTemp);
215         pMatrixRotationY(&MatTemp, yaw);           // Yaw
216         pMatrixMultiply(&MatRot, &MatRot, &MatTemp);
217         pMatrixRotationZ(&MatTemp, roll);          // Roll
218         pMatrixMultiply(&MatRot, &MatRot, &MatTemp);
219 
220         pMatrixMultiply(pOut, pOut, &MatRot);
221     }
222 
223     // 2. then, scaling
224     pMatrixScaling(&MatTemp, sx, sy, sz);
225     pMatrixMultiply(pOut, pOut, &MatTemp);
226 
227     // 3. last, translation to final world pos.
228     pMatrixTranslation(&MatTemp, xpos, ypos, zpos);
229     pMatrixMultiply(pOut, pOut, &MatTemp);
230 }
231 
MakeProjectionMatrix(D3DXMATRIX * pOut,const float near_plane,const float far_plane,const float fov_horiz,const float fov_vert)232 void MakeProjectionMatrix( D3DXMATRIX* pOut,
233                            const float near_plane, // Distance to near clipping plane
234                            const float far_plane,  // Distance to far clipping plane
235                            const float fov_horiz,  // Horizontal field of view angle, in radians
236                            const float fov_vert)   // Vertical field of view angle, in radians
237 {
238     float w = (float)1/tanf(fov_horiz*0.5f);  // 1/tan(x) == cot(x)
239     float h = (float)1/tanf(fov_vert*0.5f);   // 1/tan(x) == cot(x)
240     float Q = far_plane/(far_plane - near_plane);
241 
242     ZeroMemory(pOut, sizeof(D3DXMATRIX));
243     pOut->_11 = w;
244     pOut->_22 = h;
245     pOut->_33 = Q;
246     pOut->_43 = -Q*near_plane;
247     pOut->_34 = 1;
248 }
249 
GetWinampSongTitle(HWND hWndWinamp,wchar_t * szSongTitle,int nSize)250 void GetWinampSongTitle(HWND hWndWinamp, wchar_t *szSongTitle, int nSize)
251 {
252     szSongTitle[0] = 0;
253 	lstrcpynW(szSongTitle, (wchar_t*)SendMessage(hWndWinamp, WM_WA_IPC,
254 									 SendMessage(hWndWinamp, WM_WA_IPC, 0 , IPC_GETLISTPOS),
255 									 IPC_GETPLAYLISTTITLEW), nSize);
256 }
257 
GetWinampSongPosAsText(HWND hWndWinamp,wchar_t * szSongPos)258 void GetWinampSongPosAsText(HWND hWndWinamp, wchar_t *szSongPos)
259 {
260     // note: size(szSongPos[]) must be at least 64.
261     szSongPos[0] = 0;
262 	int nSongPosMS = SendMessage(hWndWinamp,WM_USER,0,105);
263     if (nSongPosMS > 0)
264     {
265 		wchar_t tmp[16];
266 		float time_s = nSongPosMS*0.001f;
267 		int minutes = (int)(time_s/60);
268 		time_s -= minutes*60;
269 		int seconds = (int)time_s;
270 		time_s -= seconds;
271 		int dsec = (int)(time_s*100);
272 		swprintf(tmp, L"%.02f", dsec/100.0f);
273 		swprintf(szSongPos, L"%d:%02d%s", minutes, seconds, tmp+1);
274     }
275 }
276 
GetWinampSongLenAsText(HWND hWndWinamp,wchar_t * szSongLen)277 void GetWinampSongLenAsText(HWND hWndWinamp, wchar_t *szSongLen)
278 {
279     // note: size(szSongLen[]) must be at least 64.
280     szSongLen[0] = 0;
281 	int nSongLenMS = SendMessage(hWndWinamp,WM_USER,1,105)*1000;
282     if (nSongLenMS > 0)
283     {
284 		int len_s = nSongLenMS/1000;
285 		int minutes = len_s/60;
286 		int seconds = len_s - minutes*60;
287 		swprintf(szSongLen, L"%d:%02d", minutes, seconds);
288     }
289 }
290 
GetWinampSongPos(HWND hWndWinamp)291 float GetWinampSongPos(HWND hWndWinamp)
292 {
293     // returns answer in seconds
294     return (float)SendMessage(hWndWinamp,WM_USER,0,105)*0.001f;
295 }
296 
GetWinampSongLen(HWND hWndWinamp)297 float GetWinampSongLen(HWND hWndWinamp)
298 {
299     // returns answer in seconds
300 	return (float)SendMessage(hWndWinamp,WM_USER,1,105);
301 }
302 
GetDX9TexFormatBitsPerPixel(D3DFORMAT fmt)303 int GetDX9TexFormatBitsPerPixel(D3DFORMAT fmt)
304 {
305     switch(fmt)
306     {
307     case D3DFMT_DXT1:   // 64 bits for each 4x4 pixels = 4 bits per pixel.  No Alpha channel.
308       return 4; // bytes per pixel
309 
310     case D3DFMT_DXT2:   // 128 bits for each 4x4 pixels = 8 bits per pixel.  RGB+A.
311     case D3DFMT_DXT3:   // 128 bits for each 4x4 pixels = 8 bits per pixel.  RGB+A.
312     case D3DFMT_DXT4:   // 128 bits for each 4x4 pixels = 8 bits per pixel.  RGB+A.
313     case D3DFMT_DXT5:   // 128 bits for each 4x4 pixels = 8 bits per pixel.  RGB+A.
314     case D3DFMT_R3G3B2: // 8-bit RGB texture format using 3 bits for red, 3 bits for green, and 2 bits for blue.
315     case D3DFMT_A8:   // 8-bit alpha only.
316     case D3DFMT_A8P8: // 8-bit color indexed with 8 bits of alpha.
317     case D3DFMT_P8:   // 8-bit color indexed.
318     case D3DFMT_L8:   // 8-bit luminance only.
319     case D3DFMT_A4L4: // 8-bit using 4 bits each for alpha and luminance.
320       return 8;
321 
322     case D3DFMT_R5G6B5:   // 16-bit RGB pixel format with 5 bits for red, 6 bits for green, and 5 bits for blue.
323     case D3DFMT_X1R5G5B5: // 16-bit pixel format where 5 bits are reserved for each color.
324     case D3DFMT_A1R5G5B5: // 16-bit pixel format where 5 bits are reserved for each color and 1 bit is reserved for alpha.
325     case D3DFMT_A4R4G4B4: // 16-bit ARGB pixel format with 4 bits for each channel.
326     case D3DFMT_R16F:
327     case D3DFMT_A8R3G3B2: // 16-bit ARGB texture format using 8 bits for alpha, 3 bits each for red and green, and 2 bits for blue.
328     case D3DFMT_X4R4G4B4: // 16-bit RGB pixel format using 4 bits for each color.
329     case D3DFMT_L16:      // 16-bit luminance only.
330     case D3DFMT_A8L8:     // 16-bit using 8 bits each for alpha and luminance.
331     case D3DFMT_CxV8U8:
332     case D3DFMT_V8U8:
333     case D3DFMT_L6V5U5:
334       return 16;
335 
336     case D3DFMT_G16R16F:
337     case D3DFMT_R32F:          // 32-bit float format using 32 bits for the red channel.
338     case D3DFMT_A8R8G8B8:      // 32-bit ARGB pixel format with alpha, using 8 bits per channel.
339     case D3DFMT_X8R8G8B8:      // 32-bit RGB pixel format, where 8 bits are reserved for each color.
340     case D3DFMT_A8B8G8R8:      // 32-bit ARGB pixel format with alpha, using 8 bits per channel.
341     case D3DFMT_X8B8G8R8:      // 32-bit RGB pixel format, where 8 bits are reserved for each color.
342     case D3DFMT_G16R16:        // 32-bit pixel format using 16 bits each for green and red.
343     case D3DFMT_A2R10G10B10:   // 32-bit pixel format using 10 bits each for red, green, and blue, and 2 bits for alpha.
344     case D3DFMT_A2B10G10R10:   // 32-bit pixel format using 10 bits for each color and 2 bits for alpha.
345     case D3DFMT_R8G8B8:        // 24-bit RGB pixel format with 8 bits per channel.
346     case D3DFMT_X8L8V8U8:
347     case D3DFMT_Q8W8V8U8:
348     case D3DFMT_V16U16:
349       return 32;
350 
351     case D3DFMT_A16B16G16R16F:
352     case D3DFMT_A16B16G16R16:  // 64-bit pixel format using 16 bits for each component.
353     case D3DFMT_G32R32F:       // 64-bit float format using 32 bits for the red channel and 32 bits for the green channel.
354       return 64;
355 
356     case D3DFMT_A32B32G32R32F:
357       return 128;
358     }
359 
360     return 32;
361 }