• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2 
3  @file         Shell/PVRShell.cpp
4  @copyright    Copyright (c) Imagination Technologies Limited.
5  @brief        Makes programming for 3D APIs easier by wrapping surface
6                initialization, Texture allocation and other functions for use by a demo.
7 
8 ******************************************************************************/
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <stdarg.h>
14 #include <math.h>
15 
16 #include "PVRShell.h"
17 #include "PVRShellOS.h"
18 #include "PVRShellAPI.h"
19 #include "PVRShellImpl.h"
20 
21 /*! This file simply defines a version string. It can be commented out. */
22 #include "sdkver.h"
23 #ifndef PVRSDK_VERSION
24 #define PVRSDK_VERSION "n.nn.nn.nnnn"
25 #endif
26 
27 /*! Define to automatically stop the app after x frames. If negative, run forever. */
28 #ifndef PVRSHELL_QUIT_AFTER_FRAME
29 #define PVRSHELL_QUIT_AFTER_FRAME -1
30 #endif
31 
32 /*! Define to automatically stop the app after x amount of seconds. If negative, run forever. */
33 #ifndef PVRSHELL_QUIT_AFTER_TIME
34 #define PVRSHELL_QUIT_AFTER_TIME -1
35 #endif
36 
37 /*! Define for the screen shot file name. */
38 #define PVRSHELL_SCREENSHOT_NAME	"PVRShell"
39 
40 #if defined(_WIN32)
41 #define snprintf _snprintf
42 #endif
43 
44 // No Doxygen for CPP files, due to documentation duplication
45 /// @cond NO_DOXYGEN
46 
47 // Define DISABLE_SWIPE_MAPPING to disable the PVRShell's simple mapping of swipes to key commands.
48 //#define DISABLE_SWIPE_MAPPING 1
49 /*****************************************************************************
50 ** Prototypes
51 *****************************************************************************/
52 static bool StringCopy(char *&pszStr, const char * const pszSrc);
53 
54 /****************************************************************************
55 ** Class: PVRShell
56 ****************************************************************************/
57 
58 /*!***********************************************************************
59  @brief		Constructor
60 *************************************************************************/
PVRShell()61 PVRShell::PVRShell()
62 {
63 	m_pShellInit = NULL;
64 	m_pShellData = new PVRShellData;
65 
66 	m_pShellData->nShellPosX=0;
67 	m_pShellData->nShellPosY=0;
68 
69 	m_pShellData->bFullScreen = false;	// note this may be overridden by some OS versions of PVRShell
70 
71 	m_pShellData->nAASamples= 0;
72 	m_pShellData->nColorBPP = 0;
73 	m_pShellData->nDepthBPP = 0;
74 
75 	m_pShellData->nDieAfterFrames = PVRSHELL_QUIT_AFTER_FRAME;
76 	m_pShellData->fDieAfterTime = PVRSHELL_QUIT_AFTER_TIME;
77 
78 	m_pShellData->bNeedPbuffer = false;
79 	m_pShellData->bNeedPixmap = false;
80 	m_pShellData->bNeedPixmapDisableCopy = false;
81 	m_pShellData->bNeedZbuffer = true;
82 	m_pShellData->bLockableBackBuffer = false;
83 	m_pShellData->bSoftwareRender = false;
84 	m_pShellData->bNeedStencilBuffer = false;
85 
86 	m_pShellData->bNeedAlphaFormatPre = false;
87 	m_pShellData->bUsingPowerSaving = true;
88 	m_pShellData->bOutputInfo = false;
89 	m_pShellData->bNoShellSwapBuffer = false;
90 
91 	m_pShellData->pszAppName = 0;
92 	m_pShellData->pszExitMessage = 0;
93 
94 	m_pShellData->nSwapInterval = 1;
95 	m_pShellData->nInitRepeats = 0;
96 
97 	m_pShellData->nCaptureFrameStart = -1;
98 	m_pShellData->nCaptureFrameStop  = -1;
99 	m_pShellData->nCaptureFrameScale = 1;
100 
101 	m_pShellData->nPriority = 2;
102 
103 	m_pShellData->bForceFrameTime = false;
104 	m_pShellData->nFrameTime = 33;
105 
106 	// Internal Data
107 	m_pShellData->bShellPosWasDefault = true;
108 	m_pShellData->nShellCurFrameNum = 0;
109 #ifdef PVRSHELL_FPS_OUTPUT
110 	m_pShellData->bOutputFPS = false;
111 #endif
112 	m_pShellData->bDiscardFrameColor=false;
113 	m_pShellData->bDiscardFrameDepth=true;
114 	m_pShellData->bDiscardFrameStencil=true;
115 }
116 
117 /*!***********************************************************************
118  @brief		Destructor
119 *************************************************************************/
~PVRShell()120 PVRShell::~PVRShell()
121 {
122 	delete m_pShellData;
123 	m_pShellData = NULL;
124 }
125 
126 // Allow user to set preferences from within InitApplication
127 
128 /*!***********************************************************************
129  @brief     This function is used to pass preferences to the PVRShell.
130             If used, this function must be called from InitApplication().
131  @param[in] prefName    Name of preference to set to value
132  @param[in] value       Value
133  @return    true for success
134 *************************************************************************/
135 
PVRShellSet(const prefNameBoolEnum prefName,const bool value)136 bool PVRShell::PVRShellSet(const prefNameBoolEnum prefName, const bool value)
137 {
138 	switch(prefName)
139 	{
140 	case prefFullScreen:
141 		m_pShellData->bFullScreen = value;
142 		return true;
143 
144 	case prefPBufferContext:
145 		m_pShellData->bNeedPbuffer = value;
146 		return true;
147 
148 	case prefPixmapContext:
149 		m_pShellData->bNeedPixmap = value;
150 		return true;
151 
152 	case prefPixmapDisableCopy:
153 		m_pShellData->bNeedPixmapDisableCopy = value;
154 		return true;
155 
156 	case prefZbufferContext:
157 		m_pShellData->bNeedZbuffer = value;
158 		return true;
159 
160 	case prefLockableBackBuffer:
161 		m_pShellData->bLockableBackBuffer = value;
162 		return true;
163 
164 	case prefSoftwareRendering:
165 		m_pShellData->bSoftwareRender = value;
166 		return true;
167 
168 	case prefStencilBufferContext:
169 		m_pShellData->bNeedStencilBuffer = value;
170 		return true;
171 
172 	case prefAlphaFormatPre:
173 		m_pShellData->bNeedAlphaFormatPre = value;
174 		return true;
175 
176 	case prefPowerSaving:
177 		m_pShellData->bUsingPowerSaving = value;
178 		return true;
179 
180 	case prefOutputInfo:
181 		m_pShellData->bOutputInfo = value;
182 		return true;
183 
184 	case prefNoShellSwapBuffer:
185 		m_pShellData->bNoShellSwapBuffer = value;
186 		return true;
187 
188 	case prefForceFrameTime:
189 		m_pShellData->bForceFrameTime = value;
190 		return true;
191 
192 #ifdef PVRSHELL_FPS_OUTPUT
193 	case prefOutputFPS:
194 		m_pShellData->bOutputFPS = value;
195 		return true;
196 #endif
197 
198 	case prefDiscardColor:
199 		m_pShellData->bDiscardFrameColor = value;
200 		return true;
201 	case prefDiscardDepth:
202 		m_pShellData->bDiscardFrameDepth = value;
203 		return true;
204 	case prefDiscardStencil:
205 		m_pShellData->bDiscardFrameStencil = value;
206 		return true;
207 	default:
208 		return m_pShellInit->OsSet(prefName, value);
209 	}
210 }
211 
212 /*!***********************************************************************
213  @brief      This function is used to get parameters from the PVRShell.
214              It can be called from anywhere in the program.
215  @param[in]  prefName    Name of preference to set to value
216  @return     The requested value.
217 *************************************************************************/
218 
PVRShellGet(const prefNameBoolEnum prefName) const219 bool PVRShell::PVRShellGet(const prefNameBoolEnum prefName) const
220 {
221 	switch(prefName)
222 	{
223 	case prefFullScreen:	return m_pShellData->bFullScreen;
224 	case prefIsRotated:	return (m_pShellData->nShellDimY > m_pShellData->nShellDimX);
225 	case prefPBufferContext:	return m_pShellData->bNeedPbuffer;
226 	case prefPixmapContext:	return m_pShellData->bNeedPixmap;
227 	case prefPixmapDisableCopy:	return m_pShellData->bNeedPixmapDisableCopy;
228 	case prefZbufferContext:	return m_pShellData->bNeedZbuffer;
229 	case prefLockableBackBuffer:	return m_pShellData->bLockableBackBuffer;
230 	case prefSoftwareRendering:	return m_pShellData->bSoftwareRender;
231 	case prefNoShellSwapBuffer: return m_pShellData->bNoShellSwapBuffer;
232 	case prefStencilBufferContext:	return m_pShellData->bNeedStencilBuffer;
233 	case prefAlphaFormatPre: return m_pShellData->bNeedAlphaFormatPre;
234 	case prefPowerSaving: return m_pShellData->bUsingPowerSaving;
235 	case prefOutputInfo:	return m_pShellData->bOutputInfo;
236 	case prefForceFrameTime: return m_pShellData->bForceFrameTime;
237 #ifdef PVRSHELL_FPS_OUTPUT
238 	case prefOutputFPS: return m_pShellData->bOutputFPS;
239 #endif
240 	case prefDiscardColor: return m_pShellData->bDiscardFrameColor;
241 	case prefDiscardDepth: return m_pShellData->bDiscardFrameDepth;
242 	case prefDiscardStencil: return m_pShellData->bDiscardFrameStencil;
243 	default:	return false;
244 	}
245 }
246 
247 /*!***********************************************************************
248  @brief     This function is used to pass preferences to the PVRShell.
249             If used, this function must be called from InitApplication().
250  @param[in] prefName    Name of preference to set to value
251  @param[in] value       Value
252  @return    true for success
253 *************************************************************************/
254 
PVRShellSet(const prefNameFloatEnum prefName,const float value)255 bool PVRShell::PVRShellSet(const prefNameFloatEnum prefName, const float value)
256 {
257 	switch(prefName)
258 	{
259 	case prefQuitAfterTime:
260 		m_pShellData->fDieAfterTime = value;
261 		return true;
262 
263 	default:
264 		break;
265 	}
266 	return false;
267 }
268 
269 /*!***********************************************************************
270  @brief      This function is used to get parameters from the PVRShell.
271              It can be called from anywhere in the program.
272  @param[in]  prefName    Name of preference to set to value
273  @return     The requested value.
274 *************************************************************************/
PVRShellGet(const prefNameFloatEnum prefName) const275 float PVRShell::PVRShellGet(const prefNameFloatEnum prefName) const
276 {
277 	switch(prefName)
278 	{
279 	case prefQuitAfterTime:	return m_pShellData->fDieAfterTime;
280 	default:	return -1;
281 	}
282 }
283 
284 /*!***********************************************************************
285  @brief     This function is used to pass preferences to the PVRShell.
286             If used, this function must be called from InitApplication().
287  @param[in] prefName    Name of preference to set to value
288  @param[in] value       Value
289  @return    true for success
290 *************************************************************************/
PVRShellSet(const prefNameIntEnum prefName,const int value)291 bool PVRShell::PVRShellSet(const prefNameIntEnum prefName, const int value)
292 {
293 	switch(prefName)
294 	{
295 	case prefWidth:
296 		if(value > 0)
297 		{
298 			m_pShellData->nShellDimX = value;
299 			return true;
300 		}
301 		return false;
302 
303 	case prefHeight:
304 		if(value > 0)
305 		{
306 			m_pShellData->nShellDimY = value;
307 			return true;
308 		}
309 		return false;
310 
311 	case prefPositionX:
312 		m_pShellData->bShellPosWasDefault = false;
313 		m_pShellData->nShellPosX = value;
314 		return true;
315 
316 	case prefPositionY:
317 		m_pShellData->bShellPosWasDefault = false;
318 		m_pShellData->nShellPosY = value;
319 		return true;
320 
321 	case prefQuitAfterFrame:
322 		m_pShellData->nDieAfterFrames = value;
323 		return true;
324 
325 	case prefInitRepeats:
326 		m_pShellData->nInitRepeats = value;
327 		return true;
328 
329 	case prefAASamples:
330 		if(value >= 0)
331 		{
332 			m_pShellData->nAASamples = value;
333 			return true;
334 		}
335 		return false;
336 
337 	case prefColorBPP:
338 		if(value >= 0)
339 		{
340 			m_pShellData->nColorBPP = value;
341 			return true;
342 		}
343 		return false;
344 
345 	case prefDepthBPP:
346 		if(value >= 0)
347 		{
348 			m_pShellData->nDepthBPP = value;
349 			return true;
350 		}
351 		return false;
352 
353 	case prefRotateKeys:
354 		{
355 			switch((PVRShellKeyRotate)value)
356 			{
357 			case PVRShellKeyRotateNone:
358 				m_pShellInit->m_eKeyMapUP = PVRShellKeyNameUP;
359 				m_pShellInit->m_eKeyMapLEFT = PVRShellKeyNameLEFT;
360 				m_pShellInit->m_eKeyMapDOWN = PVRShellKeyNameDOWN;
361 				m_pShellInit->m_eKeyMapRIGHT = PVRShellKeyNameRIGHT;
362 				break;
363 			case PVRShellKeyRotate90:
364 				m_pShellInit->m_eKeyMapUP = PVRShellKeyNameLEFT;
365 				m_pShellInit->m_eKeyMapLEFT = PVRShellKeyNameDOWN;
366 				m_pShellInit->m_eKeyMapDOWN = PVRShellKeyNameRIGHT;
367 				m_pShellInit->m_eKeyMapRIGHT = PVRShellKeyNameUP;
368 				break;
369 			case PVRShellKeyRotate180:
370 				m_pShellInit->m_eKeyMapUP = PVRShellKeyNameDOWN;
371 				m_pShellInit->m_eKeyMapLEFT = PVRShellKeyNameRIGHT;
372 				m_pShellInit->m_eKeyMapDOWN = PVRShellKeyNameUP;
373 				m_pShellInit->m_eKeyMapRIGHT = PVRShellKeyNameLEFT;
374 				break;
375 			case PVRShellKeyRotate270:
376 				m_pShellInit->m_eKeyMapUP = PVRShellKeyNameRIGHT;
377 				m_pShellInit->m_eKeyMapLEFT = PVRShellKeyNameUP;
378 				m_pShellInit->m_eKeyMapDOWN = PVRShellKeyNameLEFT;
379 				m_pShellInit->m_eKeyMapRIGHT = PVRShellKeyNameDOWN;
380 				break;
381 			default:
382 				return false;
383 			}
384 		}
385 			return true;
386 	case prefCaptureFrameStart:
387 		m_pShellData->nCaptureFrameStart = value;
388 		return true;
389 	case prefCaptureFrameStop:
390 		m_pShellData->nCaptureFrameStop  = value;
391 		return true;
392 	case prefCaptureFrameScale:
393 		m_pShellData->nCaptureFrameScale  = value;
394 		return true;
395 	case prefFrameTimeValue:
396 		m_pShellData->nFrameTime = value;
397 		return true;
398 	default:
399 		{
400 			if(m_pShellInit->ApiSet(prefName, value))
401 				return true;
402 
403 			return m_pShellInit->OsSet(prefName, value);
404 		}
405 	}
406 }
407 
408 /*!***********************************************************************
409  @brief      This function is used to get parameters from the PVRShell.
410              It can be called from anywhere in the program.
411  @param[in]  prefName    Name of preference to set to value
412  @return     The requested value.
413 *************************************************************************/
PVRShellGet(const prefNameIntEnum prefName) const414 int PVRShell::PVRShellGet(const prefNameIntEnum prefName) const
415 {
416 	switch(prefName)
417 	{
418 	case prefWidth:	return m_pShellData->nShellDimX;
419 	case prefHeight:	return m_pShellData->nShellDimY;
420 	case prefPositionX:	return m_pShellData->nShellPosX;
421 	case prefPositionY:	return m_pShellData->nShellPosY;
422 	case prefQuitAfterFrame:	return m_pShellData->nDieAfterFrames;
423 	case prefSwapInterval:	return m_pShellData->nSwapInterval;
424 	case prefInitRepeats:	return m_pShellData->nInitRepeats;
425 	case prefAASamples:	return m_pShellData->nAASamples;
426 	case prefCommandLineOptNum:	return m_pShellInit->m_CommandLine.m_nOptLen;
427 	case prefColorBPP: return m_pShellData->nColorBPP;
428 	case prefDepthBPP: return m_pShellData->nDepthBPP;
429 	case prefCaptureFrameStart: return m_pShellData->nCaptureFrameStart;
430 	case prefCaptureFrameStop: return m_pShellData->nCaptureFrameStop;
431 	case prefCaptureFrameScale: return m_pShellData->nCaptureFrameScale;
432 	case prefFrameTimeValue: return m_pShellData->nFrameTime;
433 	case prefPriority: return m_pShellData->nPriority;
434 	default:
435 		{
436 			int n;
437 
438 			if(m_pShellInit->ApiGet(prefName, &n))
439 				return n;
440 			if(m_pShellInit->OsGet(prefName, &n))
441 				return n;
442 			return -1;
443 		}
444 	}
445 }
446 
447 /*!***********************************************************************
448  @brief     This function is used to pass preferences to the PVRShell.
449             If used, this function must be called from InitApplication().
450  @param[in] prefName    Name of preference to set to value
451  @param[in] value       Value
452  @return    true for success
453 *************************************************************************/
PVRShellSet(const prefNamePtrEnum prefName,const void * const ptrValue)454 bool PVRShell::PVRShellSet(const prefNamePtrEnum prefName, const void * const ptrValue)
455 {
456     PVRSHELL_UNREFERENCED_PARAMETER(prefName);
457     PVRSHELL_UNREFERENCED_PARAMETER(ptrValue);
458 	return false;
459 }
460 
461 /*!***********************************************************************
462  @brief      This function is used to get parameters from the PVRShell.
463              It can be called from anywhere in the program.
464  @param[in]  prefName    Name of preference to set to value
465  @return     The requested value.
466 *************************************************************************/
PVRShellGet(const prefNamePtrEnum prefName) const467 void *PVRShell::PVRShellGet(const prefNamePtrEnum prefName) const
468 {
469 	switch(prefName)
470 	{
471 	case prefNativeWindowType:	return m_pShellInit->OsGetNativeWindowType();
472 	case prefPointerLocation:
473 		if (m_pShellInit->m_bTouching)
474 			return m_pShellInit->m_vec2PointerLocation;
475 	break;
476 	default:
477 		{
478 			void *p;
479 
480 			if(m_pShellInit->ApiGet(prefName, &p))
481 				return p;
482 			if(m_pShellInit->OsGet(prefName, &p))
483 				return p;
484 		}
485 	}
486 	return NULL;
487 }
488 
489 /*!***********************************************************************
490  @brief     This function is used to pass preferences to the PVRShell.
491             If used, this function must be called from InitApplication().
492  @param[in] prefName    Name of preference to set to value
493  @param[in] value       Value
494  @return    true for success
495 *************************************************************************/
PVRShellSet(const prefNameConstPtrEnum prefName,const void * const ptrValue)496 bool PVRShell::PVRShellSet(const prefNameConstPtrEnum prefName, const void * const ptrValue)
497 {
498 	switch(prefName)
499 	{
500 	case prefAppName:
501 		StringCopy(m_pShellData->pszAppName, (char*)ptrValue);
502 		return true;
503 	case prefExitMessage:
504 		StringCopy(m_pShellData->pszExitMessage, (char*)ptrValue);
505 		PVRShellOutputDebug("Exit message has been set to: \"%s\".\n", ptrValue);
506 		return true;
507 	default:
508 		break;
509 	}
510 	return false;
511 }
512 
513 /*!***********************************************************************
514  @brief      This function is used to get parameters from the PVRShell.
515              It can be called from anywhere in the program.
516  @param[in]  prefName    Name of preference to set to value
517  @return     The requested value.
518 *************************************************************************/
PVRShellGet(const prefNameConstPtrEnum prefName) const519 const void *PVRShell::PVRShellGet(const prefNameConstPtrEnum prefName) const
520 {
521 	switch(prefName)
522 	{
523 	case prefAppName:
524 		return m_pShellData->pszAppName;
525 	case prefExitMessage:
526 		return m_pShellData->pszExitMessage;
527 	case prefReadPath:
528 		return m_pShellInit->GetReadPath();
529 	case prefWritePath:
530 		return m_pShellInit->GetWritePath();
531 	case prefCommandLine:
532 		return m_pShellInit->m_CommandLine.m_psOrig;
533 	case prefCommandLineOpts:
534 		return m_pShellInit->m_CommandLine.m_pOpt;
535 	case prefVersion:
536 		return PVRSDK_VERSION;
537 	default:
538 		return 0;
539 	}
540 }
541 
542 /*!***********************************************************************
543  @brief	     It will be stored as 24-bit per pixel, 8-bit per chanel RGB.
544              The memory should be freed with free() when no longer needed.
545  @param[in]	 Width		size of image to capture (relative to 0,0)
546  @param[in]	 Height		size of image to capture (relative to 0,0)
547  @param[out] pLines		receives a pointer to an area of memory containing the screen buffer.
548  @return	 true for success
549 *************************************************************************/
PVRShellScreenCaptureBuffer(const int Width,const int Height,unsigned char ** pLines)550 bool PVRShell::PVRShellScreenCaptureBuffer(const int Width, const int Height, unsigned char **pLines)
551 {
552 	/* Allocate memory for line */
553 	*pLines=(unsigned char *)calloc(Width*Height*3, sizeof(unsigned char));
554 	if (!(*pLines)) return false;
555 
556 	return m_pShellInit->ApiScreenCaptureBuffer(Width, Height, *pLines);
557 }
558 
559 /*!***********************************************************************
560  @brief 	Writes out the image data to a BMP file with basename fname.
561  @details   The file written will be fname suffixed with a number to make the file unique.
562             For example, if fname is "abc", this function will attempt
563             to save to "abc0000.bmp"; if that file already exists, it
564             will try "abc0001.bmp", repeating until a new filename is
565             found. The final filename used is returned in ofname.
566  @param[in]	 fname		base of file to save screen to
567  @param[in]	 Width		size of image to capture (relative to 0,0)
568  @param[in]	 Height		size of image to capture (relative to 0,0)
569  @param[in]  pLines		image data to write out (24bpp, 8-bit per channel RGB)
570  @param[in]  ui32PixelReplicate    expand pixels through replication (1 = no scale)
571  @param[out] ofname		If non-NULL, receives the filename actually used
572  @return	 true for success
573 *************************************************************************/
PVRShellScreenSave(const char * const fname,const int Width,const int Height,const unsigned char * const pLines,const unsigned int ui32PixelReplicate,char * const ofname)574 int PVRShell::PVRShellScreenSave(
575 	const char			* const fname,
576 	const int			Width,
577 	const int			Height,
578 	const unsigned char	* const pLines,
579 	const unsigned int	ui32PixelReplicate,
580 	char				* const ofname)
581 {
582 	char *pszFileName;
583 
584 	/*
585 		Choose a filename
586 	*/
587 	{
588 		FILE		*file = 0;
589 		const char	*pszWritePath;
590 		int			nScreenshotCount;
591 
592 		pszWritePath = (const char*)PVRShellGet(prefWritePath);
593 
594 		size_t	nFileNameSize = strlen(pszWritePath) + 200;
595 		pszFileName = (char*)malloc(nFileNameSize);
596 
597 		/* Look for the first file name that doesn't already exist */
598 		for(nScreenshotCount = 0; nScreenshotCount < 10000; ++nScreenshotCount)
599 		{
600 			snprintf(pszFileName, nFileNameSize, "%s%s%04d.bmp", pszWritePath, fname, nScreenshotCount);
601 
602 			file = fopen(pszFileName,"r");
603 			if(!file)
604 				break;
605 			fclose(file);
606 		}
607 
608 		/* If all files already exist, replace the first one */
609 		if (nScreenshotCount==10000)
610 		{
611 			snprintf(pszFileName, nFileNameSize, "%s%s0000.bmp", pszWritePath, fname);
612 			PVRShellOutputDebug("PVRShell: *WARNING* : Overwriting %s\n", pszFileName);
613 		}
614 
615 		if(ofname)	// requested the output file name
616 		{
617 			strcpy(ofname, pszFileName);
618 		}
619 	}
620 
621 	const int err = PVRShellWriteBMPFile(pszFileName, Width, Height, pLines, ui32PixelReplicate);
622 	FREE(pszFileName);
623 	if (err)
624 	{
625 		return 10*err+1;
626 	}
627 	else
628 	{
629 		// No problem occurred
630 		return 0;
631 	}
632 }
633 
634 /*!***********************************************************************
635  @brief       Swaps the bytes in pBytes from little to big endian (or vice versa)
636  @param[in]	  pBytes     The bytes to swap
637  @param[in]	  i32ByteNo  The number of bytes to swap
638 *************************************************************************/
PVRShellByteSwap(unsigned char * pBytes,int i32ByteNo)639 inline void PVRShellByteSwap(unsigned char* pBytes, int i32ByteNo)
640 {
641 	int i = 0, j = i32ByteNo - 1;
642 
643 	while(i < j)
644 	{
645 		unsigned char cTmp = pBytes[i];
646 		pBytes[i] = pBytes[j];
647 		pBytes[j] = cTmp;
648 
649 		++i;
650 		--j;
651 	}
652 }
653 
654 /*!***********************************************************************
655  @brief	        Writes out the image data to a BMP file with name fname.
656  @param[in]		pszFilename		file to save screen to
657  @param[in]		ui32Width		the width of the data
658  @param[in]		ui32Height		the height of the data
659  @param[in]		pImageData		image data to write out (24bpp, 8-bit per channel RGB)
660  @return		0 on success
661 *************************************************************************/
PVRShellWriteBMPFile(const char * const pszFilename,const unsigned int ui32Width,const unsigned int ui32Height,const void * const pImageData,const unsigned int ui32PixelReplicate)662 int PVRShell::PVRShellWriteBMPFile(
663 	const char			* const pszFilename,
664 	const unsigned int	ui32Width,
665 	const unsigned int	ui32Height,
666 	const void			* const pImageData,
667 	const unsigned int	ui32PixelReplicate)
668 {
669 #define ByteSwap(x) PVRShellByteSwap((unsigned char*) &x, sizeof(x))
670 
671 	const int		i32BMPHeaderSize = 14; /* The size of a BMP header */
672 	const int		i32BMPInfoSize   = 40; /* The size of a BMP info header */
673 	int				Result = 1;
674 	FILE*			fpDumpfile = 0;
675 
676 	fpDumpfile = fopen(pszFilename, "wb");
677 
678 	if (fpDumpfile != 0)
679 	{
680 		const short int word = 0x0001;
681 		const char * const byte = (char*) &word;
682 		bool bLittleEndian = byte[0] ? true : false;
683 
684 		unsigned int i32OutBytesPerLine = ui32Width * 3 * ui32PixelReplicate;
685 		unsigned int i32OutAlign = 0;
686 
687 		// round up to a dword boundary
688 		if(i32OutBytesPerLine & 3)
689 		{
690 			i32OutBytesPerLine |= 3;
691 			++i32OutBytesPerLine;
692 			i32OutAlign = i32OutBytesPerLine - ui32Width * 3 * ui32PixelReplicate;
693 		}
694 
695 		unsigned char *pData = (unsigned char*) pImageData;
696 
697 		{
698 			int ui32RealSize = i32OutBytesPerLine * ui32Height * ui32PixelReplicate;
699 
700 			// BMP Header
701 			unsigned short  bfType = 0x4D42;
702 			unsigned int   bfSize = i32BMPHeaderSize + i32BMPInfoSize + ui32RealSize;
703 			unsigned short  bfReserved1 = 0;
704 			unsigned short  bfReserved2 = 0;
705 			unsigned int   bfOffBits = i32BMPHeaderSize + i32BMPInfoSize;
706 
707 			// BMP Info Header
708 			unsigned int  biSize = i32BMPInfoSize;
709 			unsigned int  biWidth = ui32Width * ui32PixelReplicate;
710 			unsigned int  biHeight = ui32Height * ui32PixelReplicate;
711 			unsigned short biPlanes = 1;
712 			unsigned short biBitCount = 24;
713 			unsigned int  biCompression = 0L;
714 			unsigned int  biSizeImage = ui32RealSize;
715 			unsigned int  biXPelsPerMeter = 0;
716 			unsigned int  biYPelsPerMeter = 0;
717 			unsigned int  biClrUsed = 0;
718 			unsigned int  biClrImportant = 0;
719 
720 			if(!bLittleEndian)
721 			{
722 				for(unsigned int i = 0; i < ui32Width * ui32Height; ++i)
723 					PVRShellByteSwap(pData + (3 * i), 3);
724 
725 				ByteSwap(bfType);
726 				ByteSwap(bfSize);
727 				ByteSwap(bfOffBits);
728 				ByteSwap(biSize);
729 				ByteSwap(biWidth);
730 				ByteSwap(biHeight);
731 				ByteSwap(biPlanes);
732 				ByteSwap(biBitCount);
733 				ByteSwap(biCompression);
734 				ByteSwap(biSizeImage);
735 			}
736 
737 			// Write Header.
738 			fwrite(&bfType		, 1, sizeof(bfType)		, fpDumpfile);
739 			fwrite(&bfSize		, 1, sizeof(bfSize)		, fpDumpfile);
740 			fwrite(&bfReserved1	, 1, sizeof(bfReserved1), fpDumpfile);
741 			fwrite(&bfReserved2	, 1, sizeof(bfReserved2), fpDumpfile);
742 			fwrite(&bfOffBits	, 1, sizeof(bfOffBits)	, fpDumpfile);
743 
744 			// Write info header.
745 			fwrite(&biSize			, 1, sizeof(biSize)			, fpDumpfile);
746 			fwrite(&biWidth			, 1, sizeof(biWidth)		, fpDumpfile);
747 			fwrite(&biHeight		, 1, sizeof(biHeight)		, fpDumpfile);
748 			fwrite(&biPlanes		, 1, sizeof(biPlanes)		, fpDumpfile);
749 			fwrite(&biBitCount		, 1, sizeof(biBitCount)		, fpDumpfile);
750 			fwrite(&biCompression	, 1, sizeof(biCompression)	, fpDumpfile);
751 			fwrite(&biSizeImage		, 1, sizeof(biSizeImage)	, fpDumpfile);
752 			fwrite(&biXPelsPerMeter	, 1, sizeof(biXPelsPerMeter), fpDumpfile);
753 			fwrite(&biYPelsPerMeter	, 1, sizeof(biYPelsPerMeter), fpDumpfile);
754 			fwrite(&biClrUsed		, 1, sizeof(biClrUsed)		, fpDumpfile);
755 			fwrite(&biClrImportant	, 1, sizeof(biClrImportant)	, fpDumpfile);
756 		}
757 
758 		// Write image.
759 		for(unsigned int nY = 0; nY < ui32Height; ++nY)
760 		{
761 			const unsigned char * pRow = &pData[3 * ui32Width * nY];
762 			for(unsigned int nRepY = 0; nRepY < ui32PixelReplicate; ++nRepY)
763 			{
764 				for(unsigned int nX = 0; nX < ui32Width; ++nX)
765 				{
766 					const unsigned char * pPixel = &pRow[3 * nX];
767 					for(unsigned int nRepX = 0; nRepX < ui32PixelReplicate; ++nRepX)
768 					{
769 						fwrite(pPixel, 1, 3, fpDumpfile);
770 					}
771 				}
772 
773 				fwrite("\0\0\0\0", i32OutAlign, 1, fpDumpfile);
774 			}
775 		}
776 
777 		// Last but not least close the file.
778 		fclose(fpDumpfile);
779 
780 		Result = 0;
781 	}
782 	else
783 	{
784 		PVRShellOutputDebug("PVRShell: Failed to open \"%s\" for writing screen dump.\n", pszFilename);
785 	}
786 
787 	return Result;
788 }
789 
790 /*!***********************************************************************
791  @brief	    The number itself should be considered meaningless; an
792             application should use this function to determine how much
793             time has passed between two points (e.g. between each
794             frame).
795  @return	A value which increments once per millisecond.
796 *************************************************************************/
PVRShellGetTime()797 unsigned long PVRShell::PVRShellGetTime()
798 {
799 	if(m_pShellData->bForceFrameTime)
800 	{
801 		// Return a "time" value based on the current frame number
802 		return (unsigned long) m_pShellData->nShellCurFrameNum * m_pShellData->nFrameTime;
803 	}
804 	else
805 	{
806 		// Read timer from a platform dependant function
807 		return m_pShellInit->OsGetTime();
808 	}
809 }
810 
811 /*!***********************************************************************
812  @brief	    Check if a key was pressed. The keys on various devices
813             are mapped to the PVRShell-supported keys (listed in @a PVRShellKeyName) in
814             a platform-dependent manner, since most platforms have different input
815             devices. Check the <a href="modules.html">Modules page</a> for your OS
816             for details on how the enum values map to your device's key code input.
817  @param[in]	key		Code of the key to test
818  @return	true if key was pressed
819 *************************************************************************/
PVRShellIsKeyPressed(const PVRShellKeyName key)820 bool PVRShell::PVRShellIsKeyPressed(const PVRShellKeyName key)
821 {
822 	if(!m_pShellInit)
823 		return false;
824 
825 	return m_pShellInit->DoIsKeyPressed(key);
826 }
827 
828 // class PVRShellCommandLine
829 
830 /*!***********************************************************************
831  @brief		Constructor
832 *************************************************************************/
PVRShellCommandLine()833 PVRShellCommandLine::PVRShellCommandLine()
834 {
835 	memset(this, 0, sizeof(*this));
836 }
837 
838 /*!***********************************************************************
839 @brief		Destructor
840 *************************************************************************/
~PVRShellCommandLine()841 PVRShellCommandLine::~PVRShellCommandLine()
842 {
843 	delete [] m_psOrig;
844 	delete [] m_psSplit;
845 	FREE(m_pOpt);
846 }
847 
848 /*!***********************************************************************
849  @brief	    Set command-line options to pStr
850  @param[in]	pStr   Input string
851 *************************************************************************/
Set(const char * pStr)852 void PVRShellCommandLine::Set(const char *pStr)
853 {
854 	delete [] m_psOrig;
855 	m_psOrig = 0;
856 
857 	if(pStr)
858 	{
859 		size_t len = strlen(pStr)+1;
860 		m_psOrig = new char[len];
861 		strcpy(m_psOrig, pStr);
862 	}
863 }
864 
865 /*!***********************************************************************
866  @brief	    Prepend command-line options to m_psOrig
867  @param[in]	pStr Input string
868 *************************************************************************/
Prefix(const char * pStr)869 void PVRShellCommandLine::Prefix(const char *pStr)
870 {
871 	if(!m_psOrig)
872 		Set(pStr);
873 	else if(!pStr)
874 		return;
875 	else
876 	{
877 		char *pstmp = m_psOrig;
878 		size_t lenA = strlen(pStr);
879 		size_t TotalLen = lenA + 1 + strlen(m_psOrig);
880 
881 		m_psOrig = new char[TotalLen + 1];
882 
883 		strcpy(m_psOrig, pStr);
884 		m_psOrig[lenA] = ' ';
885 		strcpy(m_psOrig + lenA + 1, pstmp);
886 		m_psOrig[TotalLen] = '\0';
887 
888 		delete[] pstmp;
889 	}
890 }
891 
892 /*!***********************************************************************
893  @brief	    Prepend command-line options to m_psOrig from a file
894  @param[in]	pFileName   Input string
895 *************************************************************************/
PrefixFromFile(const char * pFileName)896 bool PVRShellCommandLine::PrefixFromFile(const char *pFileName)
897 {
898 	char* nl;
899 	FILE *pFile = fopen(pFileName, "rb");
900 
901 	if(pFile)
902 	{
903 		// Get the file size
904 		fseek(pFile, 0, SEEK_END);
905 		long m_Size = ftell(pFile) + 2;
906 		fseek(pFile, 0, SEEK_SET);
907 
908 		char *pFullFile = new char[m_Size];
909 
910 		if(pFullFile)
911 		{
912 			size_t offset = 0;
913 			while(fgets(pFullFile + offset, (int) (m_Size - offset), pFile))
914 			{
915 				offset = strlen(pFullFile);
916 
917 				// Replace new lines with spaces
918 				nl = strrchr(pFullFile, '\r');
919 				if(nl) *nl = ' ';
920 
921 				nl = strrchr(pFullFile, '\n');
922 				if(nl) *nl = ' ';
923 			}
924 
925 			pFullFile[offset] = '\0';
926 			Prefix(pFullFile);
927 
928 			delete[] pFullFile;
929 			fclose(pFile);
930 			return true;
931 		}
932 
933 		fclose(pFile);
934 	}
935 
936 	return false;
937 }
938 
939 /*!***********************************************************************
940  @brief	  Parse m_psOrig for command-line options and store them in m_pOpt
941 *************************************************************************/
Parse()942 void PVRShellCommandLine::Parse()
943 {
944 	size_t		len;
945 	int			nIn, nOut;
946 	bool		bInQuotes;
947 	SCmdLineOpt	opt;
948 
949 	if(!m_psOrig)
950 		return;
951 
952 	// Delete/free up any options we may have parsed recently
953 	delete [] m_psSplit;
954 	FREE(m_pOpt);
955 
956 	// Take a copy to be edited
957 	len = strlen(m_psOrig) + 1;
958 	m_psSplit = new char[len];
959 
960 	// Break the command line into options
961 	bInQuotes = false;
962 	opt.pArg = NULL;
963 	opt.pVal = NULL;
964 	nIn = -1;
965 	nOut = 0;
966 
967 	do
968 	{
969 		++nIn;
970 		if(m_psOrig[nIn] == '"')
971 		{
972 			bInQuotes = !bInQuotes;
973 		}
974 		else
975 		{
976 			if(bInQuotes && m_psOrig[nIn] != 0)
977 			{
978 				if(!opt.pArg)
979 					opt.pArg = &m_psSplit[nOut];
980 
981 				m_psSplit[nOut++] = m_psOrig[nIn];
982 			}
983 			else
984 			{
985 				switch(m_psOrig[nIn])
986 				{
987 				case '=':
988 					m_psSplit[nOut++] = 0;
989 					opt.pVal = &m_psSplit[nOut];
990 					break;
991 
992 				case ' ':
993 				case '\t':
994 				case '\0':
995 					m_psSplit[nOut++] = 0;
996 					if(opt.pArg || opt.pVal)
997 					{
998 						// Increase list length if necessary
999 						if(m_nOptLen == m_nOptMax)
1000 							m_nOptMax = m_nOptMax * 2 + 1;
1001 						SCmdLineOpt* pTmp = (SCmdLineOpt*)realloc(m_pOpt, m_nOptMax * sizeof(*m_pOpt));
1002 						if(!pTmp)
1003 						{
1004 							FREE(m_pOpt);
1005 							return;
1006 						}
1007 
1008 						m_pOpt = pTmp;
1009 
1010 						// Add option to list
1011 						m_pOpt[m_nOptLen++] = opt;
1012 						opt.pArg = NULL;
1013 						opt.pVal = NULL;
1014 					}
1015 					break;
1016 
1017 				default:
1018 					if(!opt.pArg)
1019 						opt.pArg = &m_psSplit[nOut];
1020 
1021 					m_psSplit[nOut++] = m_psOrig[nIn];
1022 					break;
1023 				}
1024 			}
1025 		}
1026 	} while(m_psOrig[nIn]);
1027 }
1028 
1029 /*!***********************************************************************
1030  @brief	      Apply the command-line options to shell
1031  @param[in]	  shell
1032 *************************************************************************/
Apply(PVRShell & shell)1033 void PVRShellCommandLine::Apply(PVRShell &shell)
1034 {
1035 	int i;
1036 	const char *arg, *val;
1037 
1038 	for(i = 0; i < m_nOptLen; ++i)
1039 	{
1040 		arg = m_pOpt[i].pArg;
1041 		val = m_pOpt[i].pVal;
1042 
1043 		if(!arg)
1044 			continue;
1045 
1046 		if(val)
1047 		{
1048 			if(_stricmp(arg, "-width") == 0)
1049 			{
1050 				shell.PVRShellSet(prefWidth, atoi(val));
1051 			}
1052 			else if(_stricmp(arg, "-height") == 0)
1053 			{
1054 				shell.PVRShellSet(prefHeight, atoi(val));
1055 			}
1056 			else if(_stricmp(arg, "-aasamples") == 0)
1057 			{
1058 				shell.PVRShellSet(prefAASamples, atoi(val));
1059 			}
1060 			else if(_stricmp(arg, "-fullscreen") == 0)
1061 			{
1062 				shell.PVRShellSet(prefFullScreen, (atoi(val) != 0));
1063 			}
1064 			else if(_stricmp(arg, "-sw") == 0)
1065 			{
1066 				shell.PVRShellSet(prefSoftwareRendering, (atoi(val) != 0));
1067 			}
1068 			else if(_stricmp(arg, "-quitafterframe") == 0 || _stricmp(arg, "-qaf") == 0)
1069 			{
1070 				shell.PVRShellSet(prefQuitAfterFrame, atoi(val));
1071 			}
1072 			else if(_stricmp(arg, "-quitaftertime") == 0 || _stricmp(arg, "-qat") == 0)
1073 			{
1074 				shell.PVRShellSet(prefQuitAfterTime, (float)atof(val));
1075 			}
1076 			else if(_stricmp(arg, "-posx") == 0)
1077 			{
1078 				shell.PVRShellSet(prefPositionX, atoi(val));
1079 			}
1080 			else if(_stricmp(arg, "-posy") == 0)
1081 			{
1082 				shell.PVRShellSet(prefPositionY, atoi(val));
1083 			}
1084 			else if(_stricmp(arg, "-vsync") == 0)
1085 			{
1086 				shell.PVRShellSet(prefSwapInterval, atoi(val));
1087 			}
1088 			else if(_stricmp(arg, "-powersaving") == 0 || _stricmp(arg, "-ps") == 0)
1089 			{
1090 				shell.PVRShellSet(prefPowerSaving, (atoi(val) != 0));
1091 			}
1092 			else if(_stricmp(arg, "-colourbpp") == 0 || _stricmp(arg, "-colorbpp") == 0 ||_stricmp(arg, "-cbpp") == 0)
1093 			{
1094 				shell.PVRShellSet(prefColorBPP, atoi(val));
1095 			}
1096 			else if(_stricmp(arg, "-depthbpp") == 0 || _stricmp(arg, "-dbpp") == 0)
1097 			{
1098 				shell.PVRShellSet(prefDepthBPP, atoi(val));
1099 			}
1100 			else if(_stricmp(arg, "-rotatekeys") == 0)
1101 			{
1102 				shell.PVRShellSet(prefRotateKeys, atoi(val));
1103 			}
1104 			else if(_stricmp(arg, "-c") == 0)
1105 			{
1106 				const char* pDash = strchr(val, '-');
1107 
1108 				shell.PVRShellSet(prefCaptureFrameStart, atoi(val));
1109 
1110 				if(!pDash)
1111 					shell.PVRShellSet(prefCaptureFrameStop, atoi(val));
1112 				else
1113 					shell.PVRShellSet(prefCaptureFrameStop, atoi(pDash + 1));
1114 			}
1115 			else if(_stricmp(arg, "-screenshotscale") == 0)
1116 			{
1117 				shell.PVRShellSet(prefCaptureFrameScale, atoi(val));
1118 			}
1119 			else if(_stricmp(arg, "-priority") == 0)
1120 			{
1121 				shell.PVRShellSet(prefPriority, atoi(val));
1122 			}
1123 			else if(_stricmp(arg, "-config") == 0)
1124 			{
1125 				shell.PVRShellSet(prefRequestedConfig, atoi(val));
1126 			}
1127 			else if(_stricmp(arg, "-display") == 0)
1128 			{
1129 				shell.PVRShellSet(prefNativeDisplay, atoi(val));
1130 			}
1131 			else if(_stricmp(arg, "-forceframetime") == 0 || _stricmp(arg, "-fft") == 0)
1132 			{
1133 				shell.PVRShellSet(prefForceFrameTime, true);
1134 				shell.PVRShellSet(prefFrameTimeValue, atoi(val));
1135 			}
1136 			else if(_stricmp(arg, "-discardframeall") == 0)
1137 			{
1138 				shell.PVRShellSet(prefDiscardColor, (atoi(val) != 0));
1139 				shell.PVRShellSet(prefDiscardDepth, (atoi(val) != 0));
1140 				shell.PVRShellSet(prefDiscardStencil, (atoi(val) != 0));
1141 			}
1142 			else if(_stricmp(arg, "-discardframecolor") == 0 || _stricmp(arg, "-discardframecolour") == 0)
1143 			{
1144 				shell.PVRShellSet(prefDiscardColor, (atoi(val) != 0));
1145 			}
1146 			else if(_stricmp(arg, "-discardframedepth") == 0)
1147 			{
1148 				shell.PVRShellSet(prefDiscardDepth, (atoi(val) != 0));
1149 			}
1150 			else if(_stricmp(arg, "-discardframestencil") == 0)
1151 			{
1152 				shell.PVRShellSet(prefDiscardStencil, (atoi(val) != 0));
1153 			}
1154 		}
1155 		else
1156 		{
1157 			if(_stricmp(arg, "-version") == 0)
1158 			{
1159 				shell.PVRShellOutputDebug("Version: \"%s\"\n", shell.PVRShellGet(prefVersion));
1160 			}
1161 #ifdef PVRSHELL_FPS_OUTPUT
1162 			else if(_stricmp(arg, "-fps") == 0)
1163 			{
1164 				shell.PVRShellSet(prefOutputFPS, true);
1165 			}
1166 #endif
1167 			else if(_stricmp(arg, "-info") == 0)
1168 			{
1169 				shell.PVRShellSet(prefOutputInfo, true);
1170 			}
1171 			else if(_stricmp(arg, "-forceframetime") == 0 || _stricmp(arg, "-fft") == 0)
1172 			{
1173 				shell.PVRShellSet(prefForceFrameTime, true);
1174 			}
1175 		}
1176 	}
1177 }
1178 
1179 // @Class  PVRShellInit
1180 
1181 /*!***********************************************************************
1182  @brief	Constructor
1183 *************************************************************************/
PVRShellInit()1184 PVRShellInit::PVRShellInit()
1185 {
1186 	memset(this, 0, sizeof(*this));
1187 }
1188 
1189 /*!***********************************************************************
1190  @brief	Destructor
1191 *************************************************************************/
~PVRShellInit()1192 PVRShellInit::~PVRShellInit()
1193 {
1194 	Deinit();
1195 
1196 	delete [] m_pReadPath;
1197 	m_pReadPath = NULL;
1198 
1199 	delete [] m_pWritePath;
1200 	m_pWritePath = NULL;
1201 }
1202 
1203 /*!***********************************************************************
1204  @brief	     PVRShell deinitialisation.
1205  @param[in]	 Shell
1206 *************************************************************************/
Deinit()1207 void PVRShellInit::Deinit()
1208 {
1209 	if(m_pShell)
1210 	{
1211 		// Is the App currently running?
1212 		if(m_eState > ePVRShellInitApp && m_eState < ePVRShellExit)
1213 		{
1214 			// If so force it to go through the exit procedure
1215 			if(m_eState < ePVRShellReleaseView)
1216 				m_eState = ePVRShellReleaseView;
1217 
1218 			// Class the App as done
1219 			gShellDone = true;
1220 
1221 			// Run through the exiting states
1222             while(Run()){};
1223 		}
1224 
1225 		delete m_pShell;
1226 		m_pShell = 0;
1227 	}
1228 }
1229 
1230 /*!***********************************************************************
1231  @brief	    PVRShell Initialisation.
1232  @Function	Init
1233  @param[in]	Shell
1234  @return	True on success and false on failure
1235 *************************************************************************/
Init()1236 bool PVRShellInit::Init()
1237 {
1238 	Deinit();
1239 
1240 	m_pShell = NewDemo();
1241 
1242 	if(!m_pShell)
1243 		return false;
1244 
1245 	m_pShell->m_pShellInit	= this;
1246 
1247 	// set default direction key mappings
1248 	m_eKeyMapDOWN = PVRShellKeyNameDOWN;
1249 	m_eKeyMapLEFT = PVRShellKeyNameLEFT;
1250 	m_eKeyMapUP = PVRShellKeyNameUP;
1251 	m_eKeyMapRIGHT = PVRShellKeyNameRIGHT;
1252 	nLastKeyPressed = PVRShellKeyNameNull;
1253 
1254 	OsInit();
1255 
1256 	gShellDone = false;
1257 	m_eState = ePVRShellInitApp;
1258 	return true;
1259 }
1260 
1261 /*!***********************************************************************
1262  @brief	    Receives the command-line from the application.
1263  @param[in]	str A string containing the command-line
1264 *************************************************************************/
CommandLine(const char * str)1265 void PVRShellInit::CommandLine(const char *str)
1266 {
1267 	m_CommandLine.Set(str);
1268 }
1269 
1270 /*!***********************************************************************
1271  @brief	    Receives the command-line from the application.
1272  @param[in]  argc Number of strings in argv
1273  @param[in]  argv An array of strings
1274 *************************************************************************/
CommandLine(int argc,char ** argv)1275 void PVRShellInit::CommandLine(int argc, char **argv)
1276 {
1277 	size_t	tot, len;
1278 	char	*buf;
1279 	int		i;
1280 
1281 	tot = 0;
1282 	for(i = 0; i < argc; ++i)
1283 		tot += strlen(argv[i]);
1284 
1285 	if(!tot)
1286 	{
1287 		CommandLine((char*) "");
1288 		return;
1289 	}
1290 
1291 	// Add room for spaces and the \0
1292 	tot += argc;
1293 
1294 	buf = new char[tot];
1295 	tot = 0;
1296 	for(i = 0; i < argc; ++i)
1297 	{
1298 		len = strlen(argv[i]);
1299 		strncpy(&buf[tot], argv[i], len);
1300 		tot += len;
1301 		buf[tot++] = ' ';
1302 	}
1303 	buf[tot-1] = 0;
1304 
1305 	CommandLine(buf);
1306 
1307 	delete [] buf;
1308 }
1309 
1310 /*!***********************************************************************
1311  @brief	    Return 'true' if the specific key has been pressed.
1312  @param[in]	key   The key we're querying for
1313 *************************************************************************/
DoIsKeyPressed(const PVRShellKeyName key)1314 bool PVRShellInit::DoIsKeyPressed(const PVRShellKeyName key)
1315 {
1316 	if(key == nLastKeyPressed)
1317 	{
1318 		nLastKeyPressed = PVRShellKeyNameNull;
1319 		return true;
1320 	}
1321 	else
1322 	{
1323 		return false;
1324 	}
1325 }
1326 
1327 /*!***********************************************************************
1328  @brief	     Used by the OS-specific code to tell the Shell that a key has been pressed.
1329  @param[in]  nKey The key that has been pressed
1330 *************************************************************************/
KeyPressed(PVRShellKeyName nKey)1331 void PVRShellInit::KeyPressed(PVRShellKeyName nKey)
1332 {
1333 	nLastKeyPressed = nKey;
1334 }
1335 
1336 /*!***********************************************************************
1337  @brief	     Used by the OS-specific code to tell the Shell that a touch has began at a location.
1338  @param[in]	 vec2Location   The position of a click/touch on the screen when it first touches
1339 *************************************************************************/
TouchBegan(const float vec2Location[2])1340 void PVRShellInit::TouchBegan(const float vec2Location[2])
1341 {
1342 	m_bTouching = true;
1343 	m_vec2PointerLocationStart[0] = m_vec2PointerLocation[0] = vec2Location[0];
1344 	m_vec2PointerLocationStart[1] = m_vec2PointerLocation[1] = vec2Location[1];
1345 }
1346 
1347 /*!***********************************************************************
1348  @brief	     Used by the OS-specific code to tell the Shell that a touch has began at a location.
1349  @param[in]	 vec2Location The position of the pointer/touch pressed on the screen
1350 *************************************************************************/
TouchMoved(const float vec2Location[2])1351 void PVRShellInit::TouchMoved(const float vec2Location[2])
1352 {
1353 	if(m_bTouching)
1354 	{
1355 		m_vec2PointerLocation[0] = vec2Location[0];
1356 		m_vec2PointerLocation[1] = vec2Location[1];
1357 	}
1358 }
1359 
1360 /*!***********************************************************************
1361  @brief	    Used by the OS-specific code to tell the Shell that the current touch has ended at a location.
1362  @param[in] vec2Location The position of the pointer/touch on the screen when it is released
1363 *************************************************************************/
TouchEnded(const float vec2Location[2])1364 void PVRShellInit::TouchEnded(const float vec2Location[2])
1365 {
1366 	if(m_bTouching)
1367 	{
1368 		m_bTouching = false;
1369 		m_vec2PointerLocationEnd[0] = m_vec2PointerLocation[0] = vec2Location[0];
1370 		m_vec2PointerLocationEnd[1] = m_vec2PointerLocation[1] = vec2Location[1];
1371 
1372 #if !defined(DISABLE_SWIPE_MAPPING)
1373 		float fX = m_vec2PointerLocationEnd[0] - m_vec2PointerLocationStart[0];
1374 		float fY = m_vec2PointerLocationEnd[1] - m_vec2PointerLocationStart[1];
1375 		float fTmp = fX * fX + fY * fY;
1376 
1377 		if(fTmp > 0.005f)
1378 		{
1379 			fTmp = 1.0f / sqrt(fTmp);
1380 			fY *= fTmp;
1381 			float fAngle = acos(fY);
1382 
1383 			const float pi = 3.1415f;
1384 			const float pi_half = pi * 0.5f;
1385 			const float error = 0.25f;
1386 
1387 			if(fAngle < error)
1388 				KeyPressed(m_eKeyMapDOWN);
1389 			else if(fAngle > (pi - error))
1390 				KeyPressed(m_eKeyMapUP);
1391 			else if(fAngle > (pi_half - error) && fAngle < (pi_half + error))
1392 				KeyPressed((fX < 0) ? m_eKeyMapLEFT : m_eKeyMapRIGHT);
1393 		}
1394 		else if(fTmp < 0.09f)
1395 		{
1396 			if (m_vec2PointerLocationEnd[0] <= 0.3f) // Left half of the screen
1397 				KeyPressed(PVRShellKeyNameACTION1);
1398 			else if (m_vec2PointerLocationEnd[0] >= 0.7f) // Right half of the screen
1399 				KeyPressed(PVRShellKeyNameACTION2);
1400 		}
1401 #endif
1402 	}
1403 }
1404 
1405 /*!***********************************************************************
1406  @brief	  Used by the OS-specific code to tell the Shell where to read external files from
1407  @return  A path the application is capable of reading from
1408 *************************************************************************/
GetReadPath() const1409 const char* PVRShellInit::GetReadPath() const
1410 {
1411 	return m_pReadPath;
1412 }
1413 
1414 /*!***********************************************************************
1415  @brief	   Used by the OS-specific code to tell the Shell where to write to
1416  @return   A path the applications is capable of writing to
1417 *************************************************************************/
GetWritePath() const1418 const char* PVRShellInit::GetWritePath() const
1419 {
1420 	return m_pWritePath;
1421 }
1422 
1423 /*!****************************************************************************
1424  @brief     Sets the default app name (to be displayed by the OS)
1425  @param[in]	str   The application name
1426 *******************************************************************************/
SetAppName(const char * const str)1427 void PVRShellInit::SetAppName(const char * const str)
1428 {
1429 	const char *pName = strrchr(str, PVRSHELL_DIR_SYM);
1430 
1431 	if(pName)
1432 	{
1433 		++pName;
1434 	}
1435 	else
1436 	{
1437 		pName = str;
1438 	}
1439 	m_pShell->PVRShellSet(prefAppName, pName);
1440 }
1441 
1442 /*!***********************************************************************
1443  @brief	     Set the path to where the application expects to read from.
1444  @param[in]  str   The read path
1445 *************************************************************************/
SetReadPath(const char * const str)1446 void PVRShellInit::SetReadPath(const char * const str)
1447 {
1448 	m_pReadPath = new char[strlen(str)+1];
1449 
1450 	if(m_pReadPath)
1451 	{
1452 		strcpy(m_pReadPath, str);
1453 		char* lastSlash = strrchr(m_pReadPath, PVRSHELL_DIR_SYM);
1454 
1455 		if(lastSlash)
1456 			lastSlash[1] = 0;
1457 	}
1458 }
1459 
1460 /*!***********************************************************************
1461  @brief     Set the path to where the application expects to write to.
1462  @param[in] str   The write path
1463 *************************************************************************/
SetWritePath(const char * const str)1464 void PVRShellInit::SetWritePath(const char * const str)
1465 {
1466 	m_pWritePath = new char[strlen(str)+1];
1467 
1468 	if(m_pWritePath)
1469 	{
1470 		strcpy(m_pWritePath, str);
1471 		char* lastSlash = strrchr(m_pWritePath, PVRSHELL_DIR_SYM);
1472 
1473 		if(lastSlash)
1474 			lastSlash[1] = 0;
1475 	}
1476 }
1477 
1478 #ifdef PVRSHELL_FPS_OUTPUT
1479 /*****************************************************************************
1480  @fn       FpsUpdate
1481  @brief    Calculates a value for frames-per-second (FPS).
1482  @details  This is only compiled in to the application if PVRSHELL_FPS_OUTPUT is defined.
1483 *****************************************************************************/
FpsUpdate()1484 void PVRShellInit::FpsUpdate()
1485 {
1486 	unsigned int ui32TimeDelta, ui32Time;
1487 
1488 	ui32Time = m_pShell->PVRShellGetTime();
1489 	++m_i32FpsFrameCnt;
1490 	ui32TimeDelta = ui32Time - m_i32FpsTimePrev;
1491 
1492 	if(ui32TimeDelta >= 1000)
1493 	{
1494 		float fFPS = 1000.0f * (float) m_i32FpsFrameCnt / (float) ui32TimeDelta;
1495 
1496 		m_pShell->PVRShellOutputDebug("PVRShell: frame %d, FPS %.1f.\n",
1497 			m_pShell->m_pShellData->nShellCurFrameNum, fFPS);
1498 
1499 		m_i32FpsFrameCnt = 0;
1500 		m_i32FpsTimePrev = ui32Time;
1501 	}
1502 }
1503 #endif
1504 
1505 /*****************************************************************************
1506  @brief    Main message loop / render loop
1507  @return   false when the app should quit
1508 *****************************************************************************/
Run()1509 bool PVRShellInit::Run()
1510 {
1511 	static unsigned long StartTime = 0;
1512 
1513 	switch(m_eState)
1514 	{
1515 	case ePVRShellInitApp:
1516 		{
1517 			// Make sure the shell isn't done
1518 			gShellDone = false;
1519 
1520 			// Prepend command-line options from PVRShellCL.txt
1521 			const char * const pCL = "PVRShellCL.txt";
1522 			const char *pPath = (const char*) m_pShell->PVRShellGet(prefReadPath);
1523 			size_t nSize = strlen(pPath) + strlen(pCL) + 1;
1524 			char *pString = new char[nSize];
1525 
1526 			if(pString)
1527 			{
1528 				snprintf(pString, nSize, "%s%s", pPath, pCL);
1529 
1530 				if(!m_CommandLine.PrefixFromFile(pString))
1531 				{
1532 					delete[] pString;
1533 					pPath = (const char*) m_pShell->PVRShellGet(prefWritePath);
1534 					nSize = strlen(pPath) + strlen(pCL) + 1;
1535 					pString = new char[nSize];
1536 
1537 					snprintf(pString, nSize, "%s%s", pPath, pCL);
1538 
1539 					if(m_CommandLine.PrefixFromFile(pString))
1540 						m_pShell->PVRShellOutputDebug("Loaded command-line options from %s.\n", pString);
1541 				}
1542 				else
1543 					m_pShell->PVRShellOutputDebug("Loaded command-line options from %s.\n", pString);
1544 
1545 				delete[] pString;
1546 			}
1547 
1548 			// Parse the command-line
1549 			m_CommandLine.Parse();
1550 
1551 #if defined(_DEBUG)
1552 			m_pShell->PVRShellOutputDebug("PVRShell command line: %d/%d\n", m_CommandLine.m_nOptLen, m_CommandLine.m_nOptMax);
1553 			for(int i = 0; i < m_CommandLine.m_nOptLen; ++i)
1554 			{
1555 				m_pShell->PVRShellOutputDebug("CL %d: \"%s\"\t= \"%s\".\n", i,
1556 					m_CommandLine.m_pOpt[i].pArg ? m_CommandLine.m_pOpt[i].pArg : "",
1557 					m_CommandLine.m_pOpt[i].pVal ? m_CommandLine.m_pOpt[i].pVal : "");
1558 			}
1559 #endif
1560 			// Call InitApplication
1561 			if(!m_pShell->InitApplication())
1562 			{
1563 				m_eState = ePVRShellExit;
1564 				return true;
1565 			}
1566 
1567 			m_eState = ePVRShellInitInstance;
1568 			return true;
1569 		}
1570 	case ePVRShellInitInstance:
1571 		{
1572 			m_CommandLine.Apply(*m_pShell);
1573 
1574 			// Output non-api specific data if required
1575 			OutputInfo();
1576 
1577 			// Perform OS initialisation
1578 			if(!OsInitOS())
1579 			{
1580 				m_pShell->PVRShellOutputDebug("InitOS failed!\n");
1581 				m_eState = ePVRShellQuitApp;
1582 				return true;
1583 			}
1584 
1585 			// Initialize the 3D API
1586 			if(!OsDoInitAPI())
1587 			{
1588 				m_pShell->PVRShellOutputDebug("InitAPI failed!\n");
1589 				m_eState = ePVRShellReleaseOS;
1590 				gShellDone = true;
1591 				return true;
1592 			}
1593 
1594 			// Output api specific data if required
1595 			OutputAPIInfo();
1596 
1597 			// Initialise the app
1598 			if(!m_pShell->InitView())
1599 			{
1600 				m_pShell->PVRShellOutputDebug("InitView failed!\n");
1601 				m_eState = ePVRShellReleaseAPI;
1602 				gShellDone = true;
1603 				return true;
1604 			}
1605 
1606 			if(StartTime==0)
1607 			{
1608 				StartTime = OsGetTime();
1609 			}
1610 
1611 			m_eState = ePVRShellRender;
1612 			return true;
1613 		}
1614 	case ePVRShellRender:
1615 		{
1616 			// Main message loop:
1617 			if(!m_pShell->RenderScene())
1618 				break;
1619 
1620 			ApiRenderComplete();
1621 			OsRenderComplete();
1622 
1623 #ifdef PVRSHELL_FPS_OUTPUT
1624 			if(m_pShell->m_pShellData->bOutputFPS)
1625 				FpsUpdate();
1626 #endif
1627 			int nCurrentFrame = m_pShell->m_pShellData->nShellCurFrameNum;
1628 
1629 			if(DoIsKeyPressed(PVRShellKeyNameScreenshot) || (nCurrentFrame >= m_pShell->m_pShellData->nCaptureFrameStart && nCurrentFrame <= m_pShell->m_pShellData->nCaptureFrameStop))
1630 			{
1631 				unsigned char *pBuf;
1632 				const int nWidth = m_pShell->PVRShellGet(prefWidth);
1633 				const int nHeight = m_pShell->PVRShellGet(prefHeight);
1634 				if(m_pShell->PVRShellScreenCaptureBuffer(nWidth, nHeight, &pBuf))
1635 				{
1636 					if(m_pShell->PVRShellScreenSave(PVRSHELL_SCREENSHOT_NAME, nWidth, nHeight, pBuf, m_pShell->m_pShellData->nCaptureFrameScale) != 0)
1637 					{
1638 						m_pShell->PVRShellSet(prefExitMessage, "Screen-shot save failed.\n");
1639 					}
1640 				}
1641 				else
1642 				{
1643 					m_pShell->PVRShellSet(prefExitMessage, "Screen capture failed.\n");
1644 				}
1645 				FREE(pBuf);
1646 			}
1647 
1648 			if(DoIsKeyPressed(PVRShellKeyNameQUIT))
1649 				gShellDone = true;
1650 
1651 			if(gShellDone)
1652 				break;
1653 
1654 			/* Quit if maximum number of allowed frames is reached */
1655 			if((m_pShell->m_pShellData->nDieAfterFrames>=0) && (nCurrentFrame >= m_pShell->m_pShellData->nDieAfterFrames))
1656 				break;
1657 
1658 			/* Quit if maximum time is reached */
1659 			if((m_pShell->m_pShellData->fDieAfterTime>=0.0f) && (((OsGetTime()-StartTime)*0.001f) >= m_pShell->m_pShellData->fDieAfterTime))
1660 				break;
1661 
1662 			m_pShell->m_pShellData->nShellCurFrameNum++;
1663 			return true;
1664 		}
1665 
1666 	case ePVRShellReleaseView:
1667 		m_pShell->ReleaseView();
1668 
1669 	case ePVRShellReleaseAPI:
1670 		OsDoReleaseAPI();
1671 
1672 	case ePVRShellReleaseOS:
1673 		OsReleaseOS();
1674 
1675 		if(!gShellDone && m_pShell->m_pShellData->nInitRepeats)
1676 		{
1677 			--m_pShell->m_pShellData->nInitRepeats;
1678 			m_eState = ePVRShellInitInstance;
1679 			return true;
1680 		}
1681 
1682 		m_eState = ePVRShellQuitApp;
1683 		return true;
1684 
1685 	case ePVRShellQuitApp:
1686 		// Final app tidy-up
1687 		m_pShell->QuitApplication();
1688 		m_eState = ePVRShellExit;
1689 
1690 	case ePVRShellExit:
1691 		OsExit();
1692 		StringCopy(m_pShell->m_pShellData->pszAppName, 0);
1693 		StringCopy(m_pShell->m_pShellData->pszExitMessage, 0);
1694 		return false;
1695 	}
1696 
1697 	m_eState = (EPVRShellState)(m_eState + 1);
1698 	return true;
1699 }
1700 
1701 /*!***********************************************************************
1702 @brief	When prefOutputInfo is set to true this function outputs
1703         various pieces of non-API dependent information via
1704         PVRShellOutputDebug.
1705 *************************************************************************/
OutputInfo()1706 void PVRShellInit::OutputInfo()
1707 {
1708 	if(m_pShell->PVRShellGet(prefOutputInfo))
1709 	{
1710 		m_pShell->PVRShellOutputDebug("\n");
1711 		m_pShell->PVRShellOutputDebug("App name: %s\n"     , m_pShell->PVRShellGet(prefAppName));
1712 		m_pShell->PVRShellOutputDebug("SDK version: %s\n"  , m_pShell->PVRShellGet(prefVersion));
1713 		m_pShell->PVRShellOutputDebug("\n");
1714 		m_pShell->PVRShellOutputDebug("Read path:  %s\n"    , m_pShell->PVRShellGet(prefReadPath));
1715 		m_pShell->PVRShellOutputDebug("Write path: %s\n"   , m_pShell->PVRShellGet(prefWritePath));
1716 		m_pShell->PVRShellOutputDebug("\n");
1717 		m_pShell->PVRShellOutputDebug("Command-line: %s\n" , m_pShell->PVRShellGet(prefCommandLine));
1718 		m_pShell->PVRShellOutputDebug("\n");
1719 		m_pShell->PVRShellOutputDebug("Power saving: %s\n" , m_pShell->PVRShellGet(prefPowerSaving) ? "On" : "Off");
1720 		m_pShell->PVRShellOutputDebug("AA Samples requested: %i\n", m_pShell->PVRShellGet(prefAASamples));
1721 		m_pShell->PVRShellOutputDebug("Fullscreen: %s\n", m_pShell->PVRShellGet(prefFullScreen) ? "Yes" : "No");
1722 		m_pShell->PVRShellOutputDebug("PBuffer requested: %s\n", m_pShell->PVRShellGet(prefPBufferContext) ? "Yes" : "No");
1723 		m_pShell->PVRShellOutputDebug("ZBuffer requested: %s\n", m_pShell->PVRShellGet(prefZbufferContext) ? "Yes" : "No");
1724 		m_pShell->PVRShellOutputDebug("Stencil buffer requested: %s\n", m_pShell->PVRShellGet(prefStencilBufferContext) ? "Yes" : "No");
1725 
1726 		if(m_pShell->PVRShellGet(prefColorBPP) > 0)
1727 			m_pShell->PVRShellOutputDebug("Colour buffer size requested: %i\n", m_pShell->PVRShellGet(prefColorBPP));
1728 		if(m_pShell->PVRShellGet(prefDepthBPP) > 0)
1729 			m_pShell->PVRShellOutputDebug("Depth buffer size requested: %i\n", m_pShell->PVRShellGet(prefDepthBPP));
1730 
1731 		m_pShell->PVRShellOutputDebug("Software rendering requested: %s\n", m_pShell->PVRShellGet(prefSoftwareRendering) ? "Yes" : "No");
1732 		m_pShell->PVRShellOutputDebug("Swap Interval requested: %i\n", m_pShell->PVRShellGet(prefSwapInterval));
1733 
1734 		if(m_pShell->PVRShellGet(prefInitRepeats) > 0)
1735 			m_pShell->PVRShellOutputDebug("No of Init repeats: %i\n", m_pShell->PVRShellGet(prefInitRepeats));
1736 
1737 		if(m_pShell->PVRShellGet(prefQuitAfterFrame) != -1)
1738 			m_pShell->PVRShellOutputDebug("Quit after frame:   %i\n", m_pShell->PVRShellGet(prefQuitAfterFrame));
1739 
1740 		if(m_pShell->PVRShellGet(prefQuitAfterTime)  != -1.0f)
1741 			m_pShell->PVRShellOutputDebug("Quit after time:    %f\n", m_pShell->PVRShellGet(prefQuitAfterTime));
1742 	}
1743 }
1744 
1745 /****************************************************************************
1746 ** Local code
1747 ****************************************************************************/
1748 /*!***********************************************************************
1749  @brief	      This function copies pszSrc into pszStr.
1750  @param[out]  pszStr   The string to copy pszSrc into
1751  @param[in]	  pszSrc   The source string to copy
1752 *************************************************************************/
StringCopy(char * & pszStr,const char * const pszSrc)1753 static bool StringCopy(char *&pszStr, const char * const pszSrc)
1754 {
1755 	size_t len;
1756 
1757 	FREE(pszStr);
1758 
1759 	if(!pszSrc)
1760 		return true;
1761 
1762 	len = strlen(pszSrc)+1;
1763 	pszStr = (char*)malloc(len);
1764 	if(!pszStr)
1765 		return false;
1766 
1767 	strcpy(pszStr, pszSrc);
1768 	return true;
1769 }
1770 
1771 /// @endcond
1772 //NO_DOXYGEN
1773 
1774 /*****************************************************************************
1775 End of file (PVRShell.cpp)
1776 *****************************************************************************/
1777 
1778