1 #include "pch.h"
2 #include "texture.h"
3 
4 #include "d3dframe.h"
5 extern CD3DFramework* g_pFramework;
6 
7 ////////////////////////////////////////////////////////////////////////////
8 
9 BOOL CTexture::s_bLocked = FALSE;
10 DDSURFACEDESC2 CTexture::s_ddsd;
11 
12 
Initialize(BYTE * rgbSource,ULONG ulWidth,ULONG ulHeight,ULONG ulPitch)13 HRESULT CTexture::Initialize (BYTE *rgbSource, ULONG ulWidth, ULONG ulHeight, ULONG ulPitch)
14 {
15 	m_rgbSource = rgbSource;
16 	m_ulWidthSource = ulWidth;
17 	m_ulHeightSource = ulHeight;
18 	m_ulPitchSource = ulPitch;
19 
20 	return S_OK;
21 }
22 
Allocate(CPaletteInfo * ppi)23 HRESULT CTexture::Allocate (CPaletteInfo *ppi)
24 {
25 	HRESULT hr;
26 
27 	ASSERT (m_spddsMemory == NULL);
28 
29 	if (ppi->IsPow2 ())
30 	{
31 		m_ulWidth = 1;
32 		while (m_ulWidth < m_ulWidthSource)
33 			m_ulWidth *= 2;
34 
35 		m_ulHeight = 1;
36 		while (m_ulHeight < m_ulHeightSource)
37 			m_ulHeight *= 2;
38 	}
39 	else
40 	{
41 		m_ulWidth = m_ulWidthSource;
42 		m_ulHeight = m_ulHeightSource;
43 	}
44 
45 	if (ppi->IsSquare ())
46 	{
47 		if (m_ulHeight > m_ulWidth)
48 		{
49 			m_ulWidth = m_ulHeight;
50 		}
51 		else
52 		{
53 			m_ulHeight = m_ulWidth;
54 		}
55 	}
56 
57 	m_flAdjX = (D3DVALUE) m_ulWidthSource / (D3DVALUE) m_ulWidth;
58 	m_flAdjY = (D3DVALUE) m_ulHeightSource / (D3DVALUE) m_ulHeight;
59 
60 	DDSURFACEDESC2 ddsd;
61 	ZeroMemory (&ddsd, sizeof (ddsd));
62 	ddsd.dwSize = sizeof (ddsd);
63 	ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
64 	ddsd.dwWidth = m_ulWidth;
65 	ddsd.dwHeight = m_ulHeight;
66 	ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
67 	ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
68 	ppi->GetPixelFormat (&ddsd.ddpfPixelFormat);
69 
70 	hr = g_pFramework->GetDirectDraw ()->CreateSurface(&ddsd, &m_spddsMemory, NULL);
71 	ASSERT (SUCCEEDED (hr));
72 	if (FAILED (hr))
73 		return hr;
74 
75 	ASSERT (m_spddsMemory != NULL);
76 
77 	m_spddtMemory = m_spddsMemory;
78 
79 	DirtyMemory ();
80 
81 	DDCOLORKEY ddck;
82 	if (ppi->IsIndexed ())
83 	{
84 		ddck.dwColorSpaceLowValue = 255;
85 		ddck.dwColorSpaceHighValue = 255;
86 	}
87 	else
88 	{
89 		ddck.dwColorSpaceLowValue = 0;
90 		ddck.dwColorSpaceHighValue = 0;
91 	}
92 	hr = m_spddsMemory->SetColorKey (DDCKEY_SRCBLT, &ddck);
93 	ASSERT (SUCCEEDED (hr));
94 
95 	if (ppi->GetPalette () != NULL)
96 	{
97 		hr = m_spddsMemory->SetPalette (ppi->GetPalette ());
98 		ASSERT (SUCCEEDED (hr));
99 	}
100 
101 	return hr;
102 }
103 
Free(void)104 HRESULT CTexture::Free (void)
105 {
106 	HRESULT hr = S_OK;
107 
108 	m_spddtMemory = m_spddsMemory = NULL;
109 
110 	m_ulWidth = 0;
111 	m_ulHeight = 0;
112 
113 	return hr;
114 }
115 
Lock(void)116 HRESULT CTexture::Lock (void)
117 {
118 	HRESULT hr;
119 	if (!s_bLocked)
120 	{
121 		s_bLocked = TRUE;
122 
123 		s_ddsd.dwSize = sizeof (s_ddsd);
124 		hr = m_spddsMemory->Lock (
125 			NULL,
126 			&s_ddsd,
127 #ifndef NDEBUG
128 			DDLOCK_NOSYSLOCK |
129 #endif
130 			DDLOCK_WAIT,
131 			NULL);
132 		ASSERT (SUCCEEDED (hr));
133 	}
134 	else
135 	{
136 		// already locked
137 		hr = E_FAIL;
138 		ASSERT (FALSE);
139 	}
140 	return hr;
141 }
142 
Unlock(void)143 HRESULT CTexture::Unlock (void)
144 {
145 	HRESULT hr;
146 	if (s_bLocked)
147 	{
148 		hr = m_spddsMemory->Unlock (NULL);
149 		ASSERT (SUCCEEDED (hr));
150 
151 		s_bLocked = FALSE;
152 	}
153 	else
154 	{
155 		// not locked
156 		hr = E_FAIL;
157 		ASSERT (FALSE);
158 	}
159 	return hr;
160 }
161 
PlotPixel(ULONG ulX,ULONG ulY,BYTE b)162 void CTexture::PlotPixel (ULONG ulX, ULONG ulY, BYTE b)
163 {
164 	ASSERT (ulX <= m_ulWidth);
165 	ASSERT (ulY <= m_ulHeight);
166 
167 	ASSERT (s_bLocked);
168 	ASSERT (s_ddsd.lpSurface != NULL);
169 
170 	switch (s_ddsd.ddpfPixelFormat.dwRGBBitCount)
171 	{
172 		case 8:
173 		{
174 			* (((LPBYTE) s_ddsd.lpSurface) + ulX + ulY * s_ddsd.lPitch) = b;
175 
176 			break;
177 		}
178 		case 16:
179 		{
180 			WORD w;
181 			if (!(m_bTransparent && b == 255))
182 			{
183 				w = m_ppi->Read16 (b);
184 			}
185 			else
186 			{
187 				w = 0;
188 			}
189 			* (WORD *) (((LPBYTE) s_ddsd.lpSurface) + ulX * 2 + ulY * s_ddsd.lPitch) = w;
190 			break;
191 		}
192 
193 		default:
194 		{
195 			ASSERT (FALSE);
196 			break;
197 		}
198 	}
199 }
200 
SetBitmapData(BYTE * rgb,BOOL bRle)201 void CTexture::SetBitmapData (BYTE *rgb, BOOL bRle)
202 {
203 	m_rgbSource = rgb;
204 	m_bRle = bRle;
205 	DirtyMemory ();
206 }
207 
CopyFromSource(void)208 void CTexture::CopyFromSource (void)
209 {
210 	if (SUCCEEDED (Lock ()))
211 	{
212 		if (m_bRle)
213 		{
214 			PBYTE pbLine = m_rgbSource + m_ulHeightSource + 4;;
215 			for (ULONG y = 0; y < m_ulHeightSource; y ++)
216 			{
217 				ULONG x = 0;
218 				PBYTE pbSrc = pbLine;
219 
220 				while (1)
221 				{
222 					const BYTE RLE_CODE = 0xE0;
223 					BYTE b = *pbSrc++;
224 					if ((b & RLE_CODE) != RLE_CODE)
225 					{
226 						PlotPixel (x++, y, b);
227 					}
228 					else
229 					{
230 						BYTE cb = b & (~RLE_CODE);
231 						if (cb == 0)
232 							break;
233 
234 						b = *pbSrc++;
235 						while (cb--)
236 							PlotPixel (x++, y, b);
237 					}
238 				}
239 				ASSERT (x <= m_ulWidthSource);
240 
241 				pbLine += m_rgbSource [y + 4];
242 			}
243 		}
244 		else
245 		{
246 			LPBYTE lpbDest = (LPBYTE) s_ddsd.lpSurface;
247 			LPBYTE lpbSrc = m_rgbSource;
248 
249 			switch (s_ddsd.ddpfPixelFormat.dwRGBBitCount)
250 			{
251 				case 8:
252 				{
253 					for (ULONG y = m_ulHeightSource; y != 0; y--)
254 					{
255 						memcpy (lpbDest, lpbSrc, m_ulPitchSource);
256 						lpbDest += s_ddsd.lPitch;
257 						lpbSrc += m_ulPitchSource;
258 					}
259 					break;
260 				}
261 				case 16:
262 				{
263 					for (ULONG y = m_ulHeightSource; y != 0; y--)
264 					{
265 						LPBYTE lpbLineSrc = lpbSrc;
266 						LPWORD lpwLineDest = (LPWORD) lpbDest;
267 
268 						if (m_bTransparent)
269 						{
270 							for (ULONG x = m_ulWidthSource; x != 0; x--)
271 							{
272 								BYTE b = *lpbLineSrc++;
273 								*lpwLineDest++ = (b == 255) ? 0 : m_ppi->Read16 (b);
274 							}
275 						}
276 						else
277 						{
278 							for (ULONG x = m_ulWidthSource; x != 0; x--)
279 							{
280 								*lpwLineDest++ = m_ppi->Read16 (*lpbLineSrc++);
281 							}
282 						}
283 						lpbDest += s_ddsd.lPitch;
284 						lpbSrc += m_ulPitchSource;
285 					}
286 					break;
287 				}
288 
289 				default:
290 				{
291 					ASSERT (FALSE);
292 					break;
293 				}
294 			}
295 		}
296 		Unlock ();
297 	}
298 	else
299 	{
300 		ASSERT (FALSE);
301 	}
302 }
303 
CleanMemory(void)304 HRESULT CTexture::CleanMemory (void)
305 {
306 	CopyFromSource ();
307 	m_bDirtyMemory = FALSE;
308 	return S_OK;
309 }
310 
GetTexture()311 IDirect3DTexture2 *CTexture::GetTexture ()
312 {
313 	if (m_bDirtyMemory)
314 	{
315 		CleanMemory ();
316 	}
317 
318 	return m_spddtMemory;
319 }
320 
321 ////////////////////////////////////////////////////////////////////////////
322 
323 struct FindTextureData
324 {
325     DWORD           bpp;        // we want a texture format of this bpp
326     DDPIXELFORMAT   ddpf;       // place the format here
327 };
328 
329 
FindTextureCallback(LPDDPIXELFORMAT pddpf,LPVOID lParam)330 HRESULT CALLBACK FindTextureCallback(LPDDPIXELFORMAT pddpf, LPVOID lParam)
331 {
332     FindTextureData * FindData = (FindTextureData *)lParam;
333 
334     //
335     // we use GetDC/BitBlt to init textures so we only
336     // want to use formats that GetDC will support.
337     //
338     if (pddpf->dwFlags & (DDPF_ALPHA|DDPF_ALPHAPIXELS))
339         return DDENUMRET_OK;
340 
341 /*
342     if (pddpf->dwRGBBitCount == 16)
343     {
344         FindData->ddpf = ddpf;
345     }
346 
347     return DDENUMRET_OK;
348 */
349 
350 
351 //	if (!(pddpf->dwFlags & DDPF_ALPHAPIXELS))
352 //		return DDENUMRET_OK;
353 
354     if (pddpf->dwRGBBitCount < 8)
355         return DDENUMRET_OK;
356 
357     if (pddpf->dwRGBBitCount == 8 && !(pddpf->dwFlags & DDPF_PALETTEINDEXED8))
358         return DDENUMRET_OK;
359 
360     if (pddpf->dwRGBBitCount > 8 && !(pddpf->dwFlags & DDPF_RGB))
361         return DDENUMRET_OK;
362 
363     //
364     // keep the texture format that is nearest to the bitmap we have
365     //
366     if (FindData->ddpf.dwRGBBitCount == 0 ||
367 		(pddpf->dwRGBBitCount >= FindData->bpp && pddpf->dwRGBBitCount <= FindData->ddpf.dwRGBBitCount) //&&
368 		//(pddpf->dwAlphaBitDepth != 0 && pddpf->dwAlphaBitDepth > FindData->ddpf.dwAlphaBitDepth) // ALPHA BIT DEPTHS ARE REVERSED!!!!
369 		)
370     {
371         FindData->ddpf = *pddpf;
372     }
373 
374     return DDENUMRET_OK;
375 }
376 
ChooseTextureFormat(LPDIRECT3DDEVICE3 Device,DWORD bpp,DDPIXELFORMAT * pddpf)377 void ChooseTextureFormat(LPDIRECT3DDEVICE3 Device, DWORD bpp, DDPIXELFORMAT *pddpf)
378 {
379 	HRESULT hr;
380     FindTextureData FindData;
381 	ZeroMemory(&FindData, sizeof(FindData));
382     FindData.bpp = bpp;
383 	hr = Device->EnumTextureFormats(FindTextureCallback, (LPVOID)&FindData);
384     ASSERT(hr == S_OK);
385     *pddpf = FindData.ddpf;
386 }
387 
Initialize()388 HRESULT CPaletteInfo::Initialize ()
389 {
390 	m_spddpPalette = NULL;
391 
392 	//
393 	// find the best texture format to use.
394 	//
395 	ChooseTextureFormat (g_pFramework->GetD3DDevice (), 8, &m_ddpfPixelFormat);
396 
397 	m_cshftR = GetShift (m_mskR = m_ddpfPixelFormat.dwRBitMask);
398 	m_cshftG = GetShift (m_mskG = m_ddpfPixelFormat.dwGBitMask);
399 	m_cshftB = GetShift (m_mskB = m_ddpfPixelFormat.dwBBitMask);
400 
401 	HRESULT hr;
402 
403 	D3DDEVICEDESC descHAL, descHEL;
404 	descHAL.dwSize = descHEL.dwSize = sizeof (descHAL);
405 	hr = g_pFramework->GetD3DDevice ()->GetCaps (&descHAL, &descHEL);
406 	ASSERT (SUCCEEDED (hr));
407 
408 	if (!descHAL.dwFlags) {
409 		m_bPow2 = (descHEL.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) != 0;
410 		m_bSquare = (descHEL.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) != 0;
411 	} else {
412 		m_bPow2 = (descHAL.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) != 0;
413 		m_bSquare = (descHAL.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) != 0;
414 	}
415 
416 	if (IsIndexed ())
417 	{
418 		hr = g_pFramework->GetDirectDraw ()->CreatePalette (DDPCAPS_8BIT | DDPCAPS_ALLOW256, m_rgpe, &m_spddpPalette, NULL);
419 		ASSERT (SUCCEEDED (hr));
420 	}
421 
422 	return S_OK;
423 }
424 
Uninitialize()425 HRESULT CPaletteInfo::Uninitialize ()
426 {
427 	m_spddpPalette = NULL;	// smart pointer release
428 
429 	return S_OK;
430 }
431 
SetPaletteEntries(PALETTEENTRY rgpe[256])432 void CPaletteInfo::SetPaletteEntries (PALETTEENTRY rgpe [256])
433 {
434 	// okay, we don't really need to cache the palette values
435 	// we could implement ReadPalette by individual Getentries calls...
436 	memcpy (m_rgpe, rgpe, sizeof (m_rgpe));
437 
438 	if (m_spddpPalette != NULL)
439 	{
440 		HRESULT hr = m_spddpPalette->SetEntries (0, 0, 256,	m_rgpe);
441 		ASSERT (SUCCEEDED (hr));
442 	}
443 }
444 
GetPaletteEntries(PALETTEENTRY rgpe[256])445 void CPaletteInfo::GetPaletteEntries (PALETTEENTRY rgpe [256])
446 {
447 	if (m_spddpPalette != NULL)
448 	{
449 		HRESULT hr = m_spddpPalette->GetEntries (0, 0, 256,	m_rgpe);
450 		ASSERT (SUCCEEDED (hr));
451 	}
452 }
453 
454 ////////////////////////////////////////////////////////////////
455 CPaletteInfo *CTexture::m_ppi;
456 
Initialize()457 HRESULT CTextureSet::Initialize ()
458 {
459 	HRESULT hr;
460 
461 	hr = m_pi.Initialize ();
462 	ASSERT (SUCCEEDED (hr));
463 
464 	CTexture::m_ppi = &m_pi;
465 
466 	for (TEXTURE_SET::iterator iter = m_setTextures.begin ();
467 		iter != m_setTextures.end ();
468 		iter ++)
469 	{
470 		(*iter)->Allocate (&m_pi);
471 	}
472 
473 	return hr;
474 }
475 
Uninitialize()476 HRESULT CTextureSet::Uninitialize ()
477 {
478 	for (TEXTURE_SET::iterator iter = m_setTextures.begin ();
479 		iter != m_setTextures.end ();
480 		iter ++)
481 	{
482 		(*iter)->Free ();
483 	}
484 
485 	m_pi.Uninitialize ();
486 
487 	return S_OK;
488 }
489 
CreateTexture(BYTE * rgbSource,ULONG dx,ULONG dy,ULONG ulPitch)490 CTexture *CTextureSet::CreateTexture (BYTE *rgbSource, ULONG dx, ULONG dy, ULONG ulPitch)
491 {
492 	CTexture *pTexture = new CTexture;
493 
494 	pTexture->Initialize (rgbSource, dx, dy, ulPitch);
495 	pTexture->Allocate (&m_pi);
496 
497 	m_setTextures.insert (pTexture);
498 
499 	return pTexture;
500 }
501 
FreeTexture(CTexture * pTexture)502 void CTextureSet::FreeTexture (CTexture *pTexture)
503 {
504 	m_setTextures.erase (pTexture);
505 
506 	delete pTexture;
507 }
508 
DirtyTextures(void)509 void CTextureSet::DirtyTextures (void)
510 {
511 	for (TEXTURE_SET::iterator iter = m_setTextures.begin ();
512 		iter != m_setTextures.end ();
513 		iter ++)
514 	{
515 		(*iter)->DirtyMemory ();
516 	}
517 }
518 
519 
SetPaletteEntries(PALETTEENTRY rgpe[256])520 void CTextureSet::SetPaletteEntries (PALETTEENTRY rgpe [256])
521 {
522 	m_pi.SetPaletteEntries (rgpe);
523 
524 	if (!m_pi.IsIndexed ())
525 	{
526 		DirtyTextures ();
527 	}
528 }
529 
GetPaletteEntries(PALETTEENTRY rgpe[256])530 void CTextureSet::GetPaletteEntries (PALETTEENTRY rgpe [256])
531 {
532 	m_pi.GetPaletteEntries (rgpe);
533 }
534