Преглед на файлове

Merge pull request #417 from blackberry-gaming/next-cculy

Error handling improvements (6 of 7 - Game and Platform).
Sean Paul Taylor преди 13 години
родител
ревизия
8670a5339c

+ 1 - 1
gameplay/android/jni/Android.mk

@@ -16,7 +16,7 @@ LOCAL_PATH := $(call my-dir)/../../src
 
 
 include $(CLEAR_VARS)
 include $(CLEAR_VARS)
 LOCAL_MODULE    := libgameplay
 LOCAL_MODULE    := libgameplay
-LOCAL_SRC_FILES := AbsoluteLayout.cpp Animation.cpp AnimationClip.cpp AnimationController.cpp AnimationTarget.cpp AnimationValue.cpp AudioBuffer.cpp AudioController.cpp AudioListener.cpp AudioSource.cpp BoundingBox.cpp BoundingSphere.cpp Bundle.cpp Button.cpp Camera.cpp CheckBox.cpp Container.cpp Control.cpp Curve.cpp DebugNew.cpp DepthStencilTarget.cpp Effect.cpp FileSystem.cpp FlowLayout.cpp Font.cpp Form.cpp FrameBuffer.cpp Frustum.cpp Game.cpp gameplay-main-android.cpp Image.cpp Joint.cpp Label.cpp Layout.cpp Light.cpp Material.cpp MaterialParameter.cpp Matrix.cpp Mesh.cpp MeshBatch.cpp MeshPart.cpp MeshSkin.cpp Model.cpp Node.cpp ParticleEmitter.cpp Pass.cpp PhysicsCharacter.cpp PhysicsCollisionObject.cpp PhysicsCollisionShape.cpp PhysicsConstraint.cpp PhysicsController.cpp PhysicsFixedConstraint.cpp PhysicsGenericConstraint.cpp PhysicsGhostObject.cpp PhysicsHingeConstraint.cpp PhysicsMotionState.cpp PhysicsRigidBody.cpp PhysicsSocketConstraint.cpp PhysicsSpringConstraint.cpp Plane.cpp PlatformAndroid.cpp Properties.cpp Quaternion.cpp RadioButton.cpp Ray.cpp Rectangle.cpp Ref.cpp RenderState.cpp RenderTarget.cpp Scene.cpp SceneLoader.cpp Slider.cpp SpriteBatch.cpp Technique.cpp TextBox.cpp Texture.cpp Theme.cpp ThemeStyle.cpp Transform.cpp Vector2.cpp Vector3.cpp Vector4.cpp VertexAttributeBinding.cpp VertexFormat.cpp VerticalLayout.cpp
+LOCAL_SRC_FILES := AbsoluteLayout.cpp Animation.cpp AnimationClip.cpp AnimationController.cpp AnimationTarget.cpp AnimationValue.cpp AudioBuffer.cpp AudioController.cpp AudioListener.cpp AudioSource.cpp BoundingBox.cpp BoundingSphere.cpp Bundle.cpp Button.cpp Camera.cpp CheckBox.cpp Container.cpp Control.cpp Curve.cpp DebugNew.cpp DepthStencilTarget.cpp Effect.cpp FileSystem.cpp FlowLayout.cpp Font.cpp Form.cpp FrameBuffer.cpp Frustum.cpp Game.cpp gameplay-main-android.cpp Image.cpp Joint.cpp Label.cpp Layout.cpp Light.cpp Material.cpp MaterialParameter.cpp Matrix.cpp Mesh.cpp MeshBatch.cpp MeshPart.cpp MeshSkin.cpp Model.cpp Node.cpp ParticleEmitter.cpp Pass.cpp PhysicsCharacter.cpp PhysicsCollisionObject.cpp PhysicsCollisionShape.cpp PhysicsConstraint.cpp PhysicsController.cpp PhysicsFixedConstraint.cpp PhysicsGenericConstraint.cpp PhysicsGhostObject.cpp PhysicsHingeConstraint.cpp PhysicsMotionState.cpp PhysicsRigidBody.cpp PhysicsSocketConstraint.cpp PhysicsSpringConstraint.cpp Plane.cpp PlatformAndroid.cpp Properties.cpp Quaternion.cpp RadioButton.cpp Ray.cpp Rectangle.cpp Ref.cpp RenderState.cpp RenderTarget.cpp Scene.cpp SceneLoader.cpp ScrollLayout.cpp Slider.cpp SpriteBatch.cpp Technique.cpp TextBox.cpp Texture.cpp Theme.cpp ThemeStyle.cpp Transform.cpp Vector2.cpp Vector3.cpp Vector4.cpp VertexAttributeBinding.cpp VertexFormat.cpp VerticalLayout.cpp
 LOCAL_CFLAGS := -D__ANDROID__ -I"../../external-deps/bullet/include" -I"../../external-deps/libpng/include" -I"../../external-deps/oggvorbis/include" -I"../../external-deps/openal/include"
 LOCAL_CFLAGS := -D__ANDROID__ -I"../../external-deps/bullet/include" -I"../../external-deps/libpng/include" -I"../../external-deps/oggvorbis/include" -I"../../external-deps/openal/include"
 LOCAL_STATIC_LIBRARIES := android_native_app_glue
 LOCAL_STATIC_LIBRARIES := android_native_app_glue
 
 

+ 16 - 10
gameplay/src/Base.h

@@ -51,6 +51,13 @@ namespace gameplay
 extern void printError(const char* format, ...);
 extern void printError(const char* format, ...);
 }
 }
 
 
+// Current function macro.
+#ifdef WIN32
+#define __current__func__ __FUNCTION__
+#else
+#define __current__func__ __func__
+#endif
+
 // Assert macros.
 // Assert macros.
 #ifdef _DEBUG
 #ifdef _DEBUG
 #ifdef WIN32
 #ifdef WIN32
@@ -58,11 +65,10 @@ extern void printError(const char* format, ...);
 #else
 #else
 #define GP_FORCE_ASSERTION_FAILURE do { assert(0); } while (0)
 #define GP_FORCE_ASSERTION_FAILURE do { assert(0); } while (0)
 #endif
 #endif
-
 #define GP_ASSERT(expression) do { \
 #define GP_ASSERT(expression) do { \
     if (!(expression)) \
     if (!(expression)) \
     { \
     { \
-        printError("%s -- Assertion '" #expression "' failed.\n", __FUNCTION__); \
+        printError("%s -- Assertion '" #expression "' failed.\n", __current__func__); \
         GP_FORCE_ASSERTION_FAILURE; \
         GP_FORCE_ASSERTION_FAILURE; \
     } } while (0)
     } } while (0)
 #else
 #else
@@ -73,7 +79,7 @@ extern void printError(const char* format, ...);
 // Error macro.
 // Error macro.
 #define GP_ERROR(...) do \
 #define GP_ERROR(...) do \
     { \
     { \
-        printError("%s -- ", __FUNCTION__); \
+        printError("%s -- ", __current__func__); \
         printError(__VA_ARGS__); \
         printError(__VA_ARGS__); \
         printError("\n"); \
         printError("\n"); \
         GP_FORCE_ASSERTION_FAILURE; \
         GP_FORCE_ASSERTION_FAILURE; \
@@ -83,7 +89,7 @@ extern void printError(const char* format, ...);
 // Warning macro.
 // Warning macro.
 #define GP_WARN(...) do \
 #define GP_WARN(...) do \
     { \
     { \
-        printError("%s -- ", __FUNCTION__); \
+        printError("%s -- ", __current__func__); \
         printError(__VA_ARGS__); \
         printError(__VA_ARGS__); \
         printError("\n"); \
         printError("\n"); \
     } while (0)
     } while (0)
@@ -241,12 +247,12 @@ typedef GLuint RenderBufferHandle;
 #ifdef NDEBUG
 #ifdef NDEBUG
 #define GL_ASSERT( gl_code ) gl_code
 #define GL_ASSERT( gl_code ) gl_code
 #else
 #else
-#define GL_ASSERT( gl_code ) \
+#define GL_ASSERT( gl_code ) do \
     { \
     { \
         gl_code; \
         gl_code; \
         __gl_error_code = glGetError(); \
         __gl_error_code = glGetError(); \
         GP_ASSERT(__gl_error_code == GL_NO_ERROR); \
         GP_ASSERT(__gl_error_code == GL_NO_ERROR); \
-    }
+    } while(0)
 #endif
 #endif
 
 
 /**
 /**
@@ -258,7 +264,7 @@ typedef GLuint RenderBufferHandle;
  * macro can be used afterwards to check whether a GL error was
  * macro can be used afterwards to check whether a GL error was
  * encountered executing the specified code.
  * encountered executing the specified code.
  */
  */
-#define GL_CHECK( gl_code ) \
+#define GL_CHECK( gl_code ) do \
     { \
     { \
         while (glGetError() != GL_NO_ERROR) ; \
         while (glGetError() != GL_NO_ERROR) ; \
         gl_code; \
         gl_code; \
@@ -267,7 +273,7 @@ typedef GLuint RenderBufferHandle;
         { \
         { \
             GP_ERROR(#gl_code ": %d", (int)__gl_error_code); \
             GP_ERROR(#gl_code ": %d", (int)__gl_error_code); \
         } \
         } \
-    }
+    } while(0)
 
 
 // Global variable to hold GL errors
 // Global variable to hold GL errors
 extern GLenum __gl_error_code;
 extern GLenum __gl_error_code;
@@ -284,7 +290,7 @@ extern GLenum __gl_error_code;
  * The AL_LAST_ERROR macro can be used afterwards to check whether a AL error was
  * The AL_LAST_ERROR macro can be used afterwards to check whether a AL error was
  * encountered executing the specified code.
  * encountered executing the specified code.
  */
  */
-#define AL_CHECK( al_code ) \
+#define AL_CHECK( al_code ) do \
     { \
     { \
         while (alGetError() != AL_NO_ERROR) ; \
         while (alGetError() != AL_NO_ERROR) ; \
         al_code; \
         al_code; \
@@ -293,7 +299,7 @@ extern GLenum __gl_error_code;
         { \
         { \
             GP_ERROR(#al_code ": %d", (int)__al_error_code); \
             GP_ERROR(#al_code ": %d", (int)__al_error_code); \
         } \
         } \
-    }
+    } while(0)
 
 
 // Global variable to hold AL errors
 // Global variable to hold AL errors
 extern ALenum __al_error_code;
 extern ALenum __al_error_code;

+ 86 - 35
gameplay/src/FileSystem.cpp

@@ -2,13 +2,19 @@
 #include "FileSystem.h"
 #include "FileSystem.h"
 #include "Properties.h"
 #include "Properties.h"
 
 
+#include <sys/types.h>
+#include <sys/stat.h>
+
 #ifdef WIN32
 #ifdef WIN32
     #include <windows.h>
     #include <windows.h>
     #include <tchar.h>
     #include <tchar.h>
     #include <stdio.h>
     #include <stdio.h>
+    #define gp_stat _stat
+    #define gp_stat_struct struct stat
 #else
 #else
     #include <dirent.h>
     #include <dirent.h>
-    #include <sys/stat.h>
+    #define gp_stat stat
+    #define gp_stat_struct struct stat
 #endif
 #endif
 
 
 #ifdef __ANDROID__
 #ifdef __ANDROID__
@@ -19,9 +25,10 @@ extern AAssetManager* __assetManager;
 namespace gameplay
 namespace gameplay
 {
 {
 
 
+// Creates a file on the file system from the specified asset (Android-specific).
+static void createFileFromAsset(const char* path);
+
 #ifdef __ANDROID__
 #ifdef __ANDROID__
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <unistd.h>
 #include <unistd.h>
 
 
 void makepath(std::string path, int mode)
 void makepath(std::string path, int mode)
@@ -109,6 +116,8 @@ void FileSystem::loadResourceAliases(Properties* properties)
 
 
 const char* FileSystem::resolvePath(const char* path)
 const char* FileSystem::resolvePath(const char* path)
 {
 {
+    GP_ASSERT(path);
+
     size_t len = strlen(path);
     size_t len = strlen(path);
     if (len > 1 && path[0] == '@')
     if (len > 1 && path[0] == '@')
     {
     {
@@ -191,49 +200,40 @@ bool FileSystem::listFiles(const char* dirPath, std::vector<std::string>& files)
 #endif
 #endif
 }
 }
 
 
-FILE* FileSystem::openFile(const char* path, const char* mode)
+bool FileSystem::fileExists(const char* path)
 {
 {
     GP_ASSERT(path);
     GP_ASSERT(path);
 
 
     std::string fullPath(__resourcePath);
     std::string fullPath(__resourcePath);
     fullPath += resolvePath(path);
     fullPath += resolvePath(path);
 
 
-#ifdef __ANDROID__
-    std::string directoryPath = fullPath.substr(0, fullPath.rfind('/'));
-    struct stat s;
-    if (stat(directoryPath.c_str(), &s) != 0)
-        makepath(directoryPath.c_str(), 0777);
+    createFileFromAsset(path);
 
 
+    gp_stat_struct s;
+// Win32 doesn't support an asset or bundle definitions.
+#ifdef WIN32
     if (stat(fullPath.c_str(), &s) != 0)
     if (stat(fullPath.c_str(), &s) != 0)
     {
     {
-        AAsset* asset = AAssetManager_open(__assetManager, path, AASSET_MODE_RANDOM);
-        if (asset)
-        {
-            const void* data = AAsset_getBuffer(asset);
-            int length = AAsset_getLength(asset);
-            FILE* file = fopen(fullPath.c_str(), "wb");
-            if (file != NULL)
-            {
-                int ret = fwrite(data, sizeof(unsigned char), length, file);
-                if (fclose(file) != 0)
-                {
-                    GP_ERROR("Failed to close file on file system created from APK asset.");
-                    return NULL;
-                }
-                if (ret != length)
-                {
-                    GP_ERROR("Failed to write all data from APK asset to file on file system.");
-                    return NULL;
-                }
-            }
-            else
-            {
-                GP_ERROR("Failed to create file on file system from APK asset.");
-                return NULL;
-            }
-        }
+        fullPath = __resourcePath;
+        fullPath += "../../gameplay/";
+        fullPath += path;
+        
+        return stat(fullPath.c_str(), &s) == 0;
     }
     }
+    return true;
+#else
+    return stat(fullPath.c_str(), &s) == 0;
 #endif
 #endif
+}
+
+FILE* FileSystem::openFile(const char* path, const char* mode)
+{
+    GP_ASSERT(path);
+
+    std::string fullPath(__resourcePath);
+    fullPath += resolvePath(path);
+
+    createFileFromAsset(path);
     
     
     FILE* fp = fopen(fullPath.c_str(), mode);
     FILE* fp = fopen(fullPath.c_str(), mode);
     
     
@@ -301,4 +301,55 @@ char* FileSystem::readAll(const char* filePath, int* fileSize)
     return buffer;
     return buffer;
 }
 }
 
 
+void createFileFromAsset(const char* path)
+{
+#ifdef __ANDROID__
+    static std::set<std::string> upToDateAssets;
+
+    GP_ASSERT(path);
+    std::string fullPath(__resourcePath);
+    fullPath += FileSystem::resolvePath(path);
+
+    std::string directoryPath = fullPath.substr(0, fullPath.rfind('/'));
+    struct stat s;
+    if (stat(directoryPath.c_str(), &s) != 0)
+        makepath(directoryPath.c_str(), 0777);
+
+    // To ensure that the files on the file system corresponding to the assets in the APK bundle
+    // are always up to date (and in sync), we copy them from the APK to the file system once
+    // for each time the process (game) runs.
+    if (upToDateAssets.find(fullPath) == upToDateAssets.end())
+    {
+        AAsset* asset = AAssetManager_open(__assetManager, path, AASSET_MODE_RANDOM);
+        if (asset)
+        {
+            const void* data = AAsset_getBuffer(asset);
+            int length = AAsset_getLength(asset);
+            FILE* file = fopen(fullPath.c_str(), "wb");
+            if (file != NULL)
+            {
+                int ret = fwrite(data, sizeof(unsigned char), length, file);
+                if (fclose(file) != 0)
+                {
+                    GP_ERROR("Failed to close file on file system created from APK asset '%s'.", path);
+                    return;
+                }
+                if (ret != length)
+                {
+                    GP_ERROR("Failed to write all data from APK asset '%s' to file on file system.", path);
+                    return;
+                }
+            }
+            else
+            {
+                GP_ERROR("Failed to create file on file system from APK asset '%s'.", path);
+                return;
+            }
+
+            upToDateAssets.insert(fullPath);
+        }
+    }
+#endif
+}
+
 }
 }

+ 8 - 0
gameplay/src/FileSystem.h

@@ -92,6 +92,14 @@ public:
      */
      */
     static bool listFiles(const char* dirPath, std::vector<std::string>& files);
     static bool listFiles(const char* dirPath, std::vector<std::string>& files);
 
 
+    /**
+     * Checks if the file at the given path exists.
+     * 
+     * @param path The path to the file.
+     * @return <code>true</code> if the file exists; <code>false</code> otherwise.
+     */
+    static bool fileExists(const char* path);
+
     /**
     /**
      * Opens the specified file.
      * Opens the specified file.
      *
      *

+ 30 - 16
gameplay/src/Game.cpp

@@ -34,7 +34,7 @@ Game::~Game()
 {
 {
     // Do not call any virtual functions from the destructor.
     // Do not call any virtual functions from the destructor.
     // Finalization is done from outside this class.
     // Finalization is done from outside this class.
-    delete _timeEvents;
+    SAFE_DELETE(_timeEvents);
 #ifdef GAMEPLAY_MEM_LEAK_DETECTION
 #ifdef GAMEPLAY_MEM_LEAK_DETECTION
     Ref::printLeaks();
     Ref::printLeaks();
     printMemoryLeaks();
     printMemoryLeaks();
@@ -114,6 +114,10 @@ void Game::shutdown()
     // Call user finalization.
     // Call user finalization.
     if (_state != UNINITIALIZED)
     if (_state != UNINITIALIZED)
     {
     {
+        GP_ASSERT(_animationController);
+        GP_ASSERT(_audioController);
+        GP_ASSERT(_physicsController);
+
         Platform::signalShutdown();
         Platform::signalShutdown();
         finalize();
         finalize();
 
 
@@ -140,6 +144,10 @@ void Game::pause()
 {
 {
     if (_state == RUNNING)
     if (_state == RUNNING)
     {
     {
+        GP_ASSERT(_animationController);
+        GP_ASSERT(_audioController);
+        GP_ASSERT(_physicsController);
+
         _state = PAUSED;
         _state = PAUSED;
         _pausedTimeLast = Platform::getAbsoluteTime();
         _pausedTimeLast = Platform::getAbsoluteTime();
         _animationController->pause();
         _animationController->pause();
@@ -152,6 +160,10 @@ void Game::resume()
 {
 {
     if (_state == PAUSED)
     if (_state == PAUSED)
     {
     {
+        GP_ASSERT(_animationController);
+        GP_ASSERT(_audioController);
+        GP_ASSERT(_physicsController);
+
         _state = RUNNING;
         _state = RUNNING;
         _pausedTimeTotal += Platform::getAbsoluteTime() - _pausedTimeLast;
         _pausedTimeTotal += Platform::getAbsoluteTime() - _pausedTimeLast;
         _animationController->resume();
         _animationController->resume();
@@ -175,6 +187,10 @@ void Game::frame()
 
 
     if (_state == Game::RUNNING)
     if (_state == Game::RUNNING)
     {
     {
+        GP_ASSERT(_animationController);
+        GP_ASSERT(_audioController);
+        GP_ASSERT(_physicsController);
+
         // Update Time.
         // Update Time.
         static long lastFrameTime = Game::getGameTime();
         static long lastFrameTime = Game::getGameTime();
         long frameTime = Game::getGameTime();
         long frameTime = Game::getGameTime();
@@ -288,7 +304,7 @@ void Game::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactI
 
 
 void Game::schedule(long timeOffset, TimeListener* timeListener, void* cookie)
 void Game::schedule(long timeOffset, TimeListener* timeListener, void* cookie)
 {
 {
-    GP_ASSERT(timeListener);
+    GP_ASSERT(_timeEvents);
     TimeEvent timeEvent(getGameTime() + timeOffset, timeListener, cookie);
     TimeEvent timeEvent(getGameTime() + timeOffset, timeListener, cookie);
     _timeEvents->push(timeEvent);
     _timeEvents->push(timeEvent);
 }
 }
@@ -300,6 +316,10 @@ bool Game::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
 
 
 void Game::updateOnce()
 void Game::updateOnce()
 {
 {
+    GP_ASSERT(_animationController);
+    GP_ASSERT(_audioController);
+    GP_ASSERT(_physicsController);
+
     // Update Time.
     // Update Time.
     static long lastFrameTime = Game::getGameTime();
     static long lastFrameTime = Game::getGameTime();
     long frameTime = Game::getGameTime();
     long frameTime = Game::getGameTime();
@@ -325,22 +345,15 @@ void Game::loadConfig()
     if (_properties == NULL)
     if (_properties == NULL)
     {
     {
         // Try to load custom config from file.
         // Try to load custom config from file.
-        // Check if file exists.
-        FILE* file = FileSystem::openFile("game.config", "rb");
-        if (file)
+        if (FileSystem::fileExists("game.config"))
         {
         {
-            fclose(file);
             _properties = Properties::create("game.config");
             _properties = Properties::create("game.config");
+            
+            // Load filesystem aliases.
+            Properties* aliases = _properties->getNamespace("aliases", true);
+            if (aliases)
+                FileSystem::loadResourceAliases(aliases);
         }
         }
-        else
-        {
-            _properties = new Properties();
-        }
-
-        // Load filesystem aliases
-        Properties* aliases = _properties->getNamespace("aliases", true);
-        if (aliases)
-            FileSystem::loadResourceAliases(aliases);
     }
     }
 }
 }
 
 
@@ -353,7 +366,8 @@ void Game::fireTimeEvents(long frameTime)
         {
         {
             break;
             break;
         }
         }
-        timeEvent->listener->timeEvent(frameTime - timeEvent->time, timeEvent->cookie);
+        if (timeEvent->listener)
+            timeEvent->listener->timeEvent(frameTime - timeEvent->time, timeEvent->cookie);
         _timeEvents->pop();
         _timeEvents->pop();
     }
     }
 }
 }

+ 1 - 0
gameplay/src/Game.inl

@@ -47,6 +47,7 @@ inline PhysicsController* Game::getPhysicsController() const
 template <class T>
 template <class T>
 void Game::renderOnce(T* instance, void (T::*method)(void*), void* cookie)
 void Game::renderOnce(T* instance, void (T::*method)(void*), void* cookie)
 {
 {
+    GP_ASSERT(instance);
     (instance->*method)(cookie);
     (instance->*method)(cookie);
     Platform::swapBuffers();
     Platform::swapBuffers();
 }
 }

+ 1 - 1
gameplay/src/Matrix.cpp

@@ -116,7 +116,7 @@ void Matrix::createPerspective(float fieldOfView, float aspectRatio,
 
 
     float f_n = 1.0f / (zFarPlane - zNearPlane);
     float f_n = 1.0f / (zFarPlane - zNearPlane);
     float theta = MATH_DEG_TO_RAD(fieldOfView) * 0.5f;
     float theta = MATH_DEG_TO_RAD(fieldOfView) * 0.5f;
-    if (abs(fmod(theta, MATH_PIOVER2)) < MATH_EPSILON)
+    if (fabs(fmod(theta, MATH_PIOVER2)) < MATH_EPSILON)
     {
     {
         GP_ERROR("Invalid field of view value (%d) causes attempted calculation tan(%d), which is undefined.", fieldOfView, theta);
         GP_ERROR("Invalid field of view value (%d) causes attempted calculation tan(%d), which is undefined.", fieldOfView, theta);
         return;
         return;

+ 33 - 14
gameplay/src/PlatformAndroid.cpp

@@ -11,7 +11,6 @@
 #include <android_native_app_glue.h>
 #include <android_native_app_glue.h>
 
 
 #include <android/log.h>
 #include <android/log.h>
-#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
 
 
 // Externally referenced global variables.
 // Externally referenced global variables.
 struct android_app* __state;
 struct android_app* __state;
@@ -50,19 +49,22 @@ namespace gameplay
 
 
 static long timespec2millis(struct timespec *a)
 static long timespec2millis(struct timespec *a)
 {
 {
+    GP_ASSERT(a);
     return a->tv_sec*1000 + a->tv_nsec/1000000;
     return a->tv_sec*1000 + a->tv_nsec/1000000;
 }
 }
 
 
 extern void printError(const char* format, ...)
 extern void printError(const char* format, ...)
 {
 {
+    GP_ASSERT(format);
     va_list argptr;
     va_list argptr;
     va_start(argptr, format);
     va_start(argptr, format);
-    LOGI(format, argptr);
+    __android_log_vprint(ANDROID_LOG_INFO, "gameplay-native-activity", format, argptr);
     va_end(argptr);
     va_end(argptr);
 }
 }
 
 
 static EGLenum checkErrorEGL(const char* msg)
 static EGLenum checkErrorEGL(const char* msg)
 {
 {
+    GP_ASSERT(msg);
     static const char* errmsg[] =
     static const char* errmsg[] =
     {
     {
         "EGL function succeeded",
         "EGL function succeeded",
@@ -82,7 +84,7 @@ static EGLenum checkErrorEGL(const char* msg)
         "EGL power management event has occurred",
         "EGL power management event has occurred",
     };
     };
     EGLenum error = eglGetError();
     EGLenum error = eglGetError();
-    LOGI("%s: %s\n", msg, errmsg[error - EGL_SUCCESS]);
+    printError("%s: %s.", msg, errmsg[error - EGL_SUCCESS]);
     return error;
     return error;
 }
 }
 
 
@@ -232,17 +234,21 @@ static void displayKeyboard(android_app* state, bool show)
     // ANativeActivity_showSoftInput(state->activity, ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT);
     // ANativeActivity_showSoftInput(state->activity, ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT);
     // ANativeActivity_hideSoftInput(state->activity, ANATIVEACTIVITY_HIDE_SOFT_INPUT_IMPLICIT_ONLY);
     // ANativeActivity_hideSoftInput(state->activity, ANATIVEACTIVITY_HIDE_SOFT_INPUT_IMPLICIT_ONLY);
     
     
+    GP_ASSERT(state && state->activity && state->activity->vm);
+
     // Show or hide the keyboard by calling the appropriate Java method through JNI instead.
     // Show or hide the keyboard by calling the appropriate Java method through JNI instead.
-    jint result;
     jint flags = 0;
     jint flags = 0;
     JavaVM* jvm = state->activity->vm;
     JavaVM* jvm = state->activity->vm;
-    JNIEnv* env;
+    JNIEnv* env = NULL;
     jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
     jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
-    jvm->AttachCurrentThread(&env, NULL);
+    jint result = jvm->AttachCurrentThread(&env, NULL);
     if (result == JNI_ERR)
     if (result == JNI_ERR)
-    { 
+    {
+        GP_ERROR("Failed to retrieve JVM environment to display keyboard.");
         return; 
         return; 
-    } 
+    }
+    GP_ASSERT(env);
+
     // Retrieves NativeActivity. 
     // Retrieves NativeActivity. 
     jobject lNativeActivity = state->activity->clazz;
     jobject lNativeActivity = state->activity->clazz;
     jclass ClassNativeActivity = env->GetObjectClass(lNativeActivity);
     jclass ClassNativeActivity = env->GetObjectClass(lNativeActivity);
@@ -564,7 +570,7 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
         switch (action & AMOTION_EVENT_ACTION_MASK)
         switch (action & AMOTION_EVENT_ACTION_MASK)
         {
         {
             case AMOTION_EVENT_ACTION_DOWN:
             case AMOTION_EVENT_ACTION_DOWN:
-                // Primary pointer down
+                // Primary pointer down.
                 pointerId = AMotionEvent_getPointerId(event, 0);
                 pointerId = AMotionEvent_getPointerId(event, 0);
                 gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0), pointerId);
                 gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0), pointerId);
                 __primaryTouchId = pointerId;
                 __primaryTouchId = pointerId;
@@ -578,7 +584,7 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
                 __primaryTouchId = -1;
                 __primaryTouchId = -1;
                 break;
                 break;
             case AMOTION_EVENT_ACTION_POINTER_DOWN:
             case AMOTION_EVENT_ACTION_POINTER_DOWN:
-                // Non-primary pointer down
+                // Non-primary pointer down.
                 if (__multiTouch)
                 if (__multiTouch)
                 {
                 {
                     pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
                     pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
@@ -718,15 +724,23 @@ Platform* Platform::create(Game* game)
 
 
 int Platform::enterMessagePump()
 int Platform::enterMessagePump()
 {
 {
+    GP_ASSERT(__state && __state->activity && __state->activity->vm);
+
     __initialized = false;
     __initialized = false;
     __suspended = false;
     __suspended = false;
 
 
     // Get the android application's activity.
     // Get the android application's activity.
     ANativeActivity* activity = __state->activity;
     ANativeActivity* activity = __state->activity;
     JavaVM* jvm = __state->activity->vm;
     JavaVM* jvm = __state->activity->vm;
-    JNIEnv* env;
+    JNIEnv* env = NULL;
     jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
     jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
-    jvm->AttachCurrentThread(&env, NULL);
+    jint res = jvm->AttachCurrentThread(&env, NULL);
+    if (res == JNI_ERR)
+    {
+        GP_ERROR("Failed to retrieve JVM environment when entering message pump.");
+        return -1; 
+    }
+    GP_ASSERT(env);
 
 
     // Get the package name for this app from Java.
     // Get the package name for this app from Java.
     jclass clazz = env->GetObjectClass(activity->clazz);
     jclass clazz = env->GetObjectClass(activity->clazz);
@@ -745,7 +759,7 @@ int Platform::enterMessagePump()
     FileSystem::setResourcePath(assetsPath.c_str());    
     FileSystem::setResourcePath(assetsPath.c_str());    
         
         
     // Get the asset manager to get the resources from the .apk file.
     // Get the asset manager to get the resources from the .apk file.
-    __assetManager = __state->activity->assetManager; 
+    __assetManager = activity->assetManager; 
     
     
     // Set the event call back functions.
     // Set the event call back functions.
     __state->onAppCmd = engine_handle_cmd;
     __state->onAppCmd = engine_handle_cmd;
@@ -893,16 +907,21 @@ void Platform::getAccelerometerValues(float* pitch, float* roll)
     }
     }
     else
     else
     {
     {
-        // 0
         tx = __sensorEvent.acceleration.x;
         tx = __sensorEvent.acceleration.x;
         ty = __sensorEvent.acceleration.y;
         ty = __sensorEvent.acceleration.y;
     }
     }
     tz = __sensorEvent.acceleration.z;
     tz = __sensorEvent.acceleration.z;
 
 
     if (pitch != NULL)
     if (pitch != NULL)
+    {
+        GP_ASSERT(tx * tx + tz * tz);
         *pitch = -atan(ty / sqrt(tx * tx + tz * tz)) * 180.0f * M_1_PI;
         *pitch = -atan(ty / sqrt(tx * tx + tz * tz)) * 180.0f * M_1_PI;
+    }
     if (roll != NULL)
     if (roll != NULL)
+    {
+        GP_ASSERT(ty * ty + tz * tz);
         *roll = -atan(tx / sqrt(ty * ty + tz * tz)) * 180.0f * M_1_PI;
         *roll = -atan(tx / sqrt(ty * ty + tz * tz)) * 180.0f * M_1_PI;
+    }
 }
 }
 
 
 void Platform::swapBuffers()
 void Platform::swapBuffers()

+ 110 - 33
gameplay/src/PlatformMacOSX.mm

@@ -15,11 +15,11 @@ using namespace std;
 using namespace gameplay;
 using namespace gameplay;
 
 
 // Default to 720p
 // Default to 720p
-#define WINDOW_WIDTH    1280
-#define WINDOW_HEIGHT   720
+static int __width = 1280;
+static int __height = 720;
 
 
-static const float ACCELEROMETER_FACTOR_X = 90.0f / WINDOW_WIDTH;
-static const float ACCELEROMETER_FACTOR_Y = 90.0f / WINDOW_HEIGHT;
+static float ACCELEROMETER_FACTOR_X = 90.0f / __width;
+static float ACCELEROMETER_FACTOR_Y = 90.0f / __height;
 
 
 static long __timeStart;
 static long __timeStart;
 static long __timeAbsolute;
 static long __timeAbsolute;
@@ -33,6 +33,8 @@ static bool __leftMouseDown = false;
 static bool __rightMouseDown = false;
 static bool __rightMouseDown = false;
 static bool __otherMouseDown = false;
 static bool __otherMouseDown = false;
 static bool __shiftDown = false;
 static bool __shiftDown = false;
+static char* __title = NULL;
+static bool __fullscreen = false;
 
 
 
 
 long getMachTimeInMilliseconds()
 long getMachTimeInMilliseconds()
@@ -44,6 +46,7 @@ long getMachTimeInMilliseconds()
         (void) mach_timebase_info(&s_timebase_info);
         (void) mach_timebase_info(&s_timebase_info);
     
     
     // mach_absolute_time() returns billionth of seconds, so divide by one million to get milliseconds
     // mach_absolute_time() returns billionth of seconds, so divide by one million to get milliseconds
+    GP_ASSERT(kOneMillion * s_timebase_info.denom);
     return (long)((mach_absolute_time() * s_timebase_info.numer) / (kOneMillion * s_timebase_info.denom));
     return (long)((mach_absolute_time() * s_timebase_info.numer) / (kOneMillion * s_timebase_info.denom));
 }
 }
 
 
@@ -107,7 +110,7 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
 
 
 - (id) initWithFrame: (NSRect) frame
 - (id) initWithFrame: (NSRect) frame
 {    
 {    
-    NSOpenGLPixelFormatAttribute attrs[] = 
+    NSOpenGLPixelFormatAttribute windowedAttrs[] = 
     {
     {
         NSOpenGLPFAAccelerated,
         NSOpenGLPFAAccelerated,
         NSOpenGLPFADoubleBuffer,
         NSOpenGLPFADoubleBuffer,
@@ -117,6 +120,18 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
         NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy,
         NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy,
         0
         0
     };
     };
+    NSOpenGLPixelFormatAttribute fullscreenAttrs[] = 
+    {
+        NSOpenGLPFADoubleBuffer,
+        NSOpenGLPFAScreenMask, (NSOpenGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()),
+        NSOpenGLPFAFullScreen,
+        NSOpenGLPFAColorSize, 32,
+        NSOpenGLPFADepthSize, 24,
+        NSOpenGLPFAAlphaSize, 8,
+        NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy,
+        0
+    };
+    NSOpenGLPixelFormatAttribute* attrs = __fullscreen ? fullscreenAttrs : windowedAttrs;
     
     
     NSOpenGLPixelFormat* pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
     NSOpenGLPixelFormat* pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
     if (!pf)
     if (!pf)
@@ -135,14 +150,14 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
 {
 {
     [super prepareOpenGL];
     [super prepareOpenGL];
     
     
-    NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
-    NSString* path = [bundlePath stringByAppendingString:@"/Contents/Resources/"];
-    FileSystem::setResourcePath([path cStringUsingEncoding:NSASCIIStringEncoding]);
     _game->run();
     _game->run();
     
     
-    [[self window] setLevel: NSFloatingWindowLevel];
+    if (__fullscreen)
+        [[self window] setLevel: NSMainMenuWindowLevel+1];
+    else
+        [[self window] setLevel: NSFloatingWindowLevel];
     [[self window] makeKeyAndOrderFront: self];
     [[self window] makeKeyAndOrderFront: self];
-    [[self window] setTitle: [NSString stringWithUTF8String: ""]];
+    [[self window] setTitle: [NSString stringWithUTF8String: __title ? __title : ""]];
     
     
     // Make all the OpenGL calls to setup rendering and build the necessary rendering objects
     // Make all the OpenGL calls to setup rendering and build the necessary rendering objects
     [[self openGLContext] makeCurrentContext];
     [[self openGLContext] makeCurrentContext];
@@ -160,6 +175,10 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
     CGLPixelFormatObj cglPixelFormat = (CGLPixelFormatObj)[[self pixelFormat] CGLPixelFormatObj];
     CGLPixelFormatObj cglPixelFormat = (CGLPixelFormatObj)[[self pixelFormat] CGLPixelFormatObj];
     CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat);
     CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat);
     
     
+    GLint dim[2] = {__width, __height};
+    CGLSetParameter(cglContext, kCGLCPSurfaceBackingSize, dim);
+    CGLEnable(cglContext, kCGLCESurfaceBackingSize);
+    
     // Activate the display link
     // Activate the display link
     CVDisplayLinkStart(displayLink);
     CVDisplayLinkStart(displayLink);
 }
 }
@@ -204,20 +223,20 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
 {
 {
     NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
     NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
     __leftMouseDown = true;
     __leftMouseDown = true;
-    [self mouse: Mouse::MOUSE_PRESS_LEFT_BUTTON orTouchEvent: Touch::TOUCH_PRESS x: point.x y: WINDOW_HEIGHT - point.y s: 0];
+    [self mouse: Mouse::MOUSE_PRESS_LEFT_BUTTON orTouchEvent: Touch::TOUCH_PRESS x: point.x y: __height - point.y s: 0];
 }
 }
 
 
 - (void) mouseUp: (NSEvent*) event
 - (void) mouseUp: (NSEvent*) event
 {
 {
      NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
      NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
     __leftMouseDown = false;
     __leftMouseDown = false;
-    [self mouse: Mouse::MOUSE_RELEASE_LEFT_BUTTON orTouchEvent: Touch::TOUCH_RELEASE x: point.x y: WINDOW_HEIGHT - point.y s: 0];
+    [self mouse: Mouse::MOUSE_RELEASE_LEFT_BUTTON orTouchEvent: Touch::TOUCH_RELEASE x: point.x y: __height - point.y s: 0];
 }
 }
 
 
 - (void)mouseMoved:(NSEvent *) event 
 - (void)mouseMoved:(NSEvent *) event 
 {
 {
     NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
     NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
-    Game::getInstance()->mouseEvent(Mouse::MOUSE_MOVE, point.x, WINDOW_HEIGHT - point.y, 0);
+    Game::getInstance()->mouseEvent(Mouse::MOUSE_MOVE, point.x, __height - point.y, 0);
 }
 }
 
 
 - (void) mouseDragged: (NSEvent*) event
 - (void) mouseDragged: (NSEvent*) event
@@ -225,7 +244,7 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
      NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
      NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
     if (__leftMouseDown)
     if (__leftMouseDown)
     {
     {
-        [self mouse: Mouse::MOUSE_MOVE orTouchEvent: Touch::TOUCH_MOVE x: point.x y: WINDOW_HEIGHT - point.y s: 0];
+        [self mouse: Mouse::MOUSE_MOVE orTouchEvent: Touch::TOUCH_MOVE x: point.x y: __height - point.y s: 0];
     }
     }
 }
 }
 
 
@@ -234,15 +253,15 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
     __rightMouseDown = true;
     __rightMouseDown = true;
      NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
      NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
     __lx = point.x;
     __lx = point.x;
-    __ly = WINDOW_HEIGHT - point.y;    
-    _game->mouseEvent(Mouse::MOUSE_PRESS_RIGHT_BUTTON, point.x, WINDOW_HEIGHT - point.y, 0);
+    __ly = __height - point.y;    
+    _game->mouseEvent(Mouse::MOUSE_PRESS_RIGHT_BUTTON, point.x, __height - point.y, 0);
 }
 }
 
 
 - (void) rightMouseUp: (NSEvent*) event
 - (void) rightMouseUp: (NSEvent*) event
 {
 {
    __rightMouseDown = false;
    __rightMouseDown = false;
     NSPoint point = [event locationInWindow];
     NSPoint point = [event locationInWindow];
-    _game->mouseEvent(Mouse::MOUSE_RELEASE_RIGHT_BUTTON, point.x, WINDOW_HEIGHT - point.y, 0);
+    _game->mouseEvent(Mouse::MOUSE_RELEASE_RIGHT_BUTTON, point.x, __height - point.y, 0);
 }
 }
 
 
 - (void) rightMouseDragged: (NSEvent*) event
 - (void) rightMouseDragged: (NSEvent*) event
@@ -252,7 +271,7 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
     {
     {
         // Update the pitch and roll by adding the scaled deltas.
         // Update the pitch and roll by adding the scaled deltas.
         __roll += (float)(point.x - __lx) * ACCELEROMETER_FACTOR_X;
         __roll += (float)(point.x - __lx) * ACCELEROMETER_FACTOR_X;
-        __pitch -= -(float)(point.y - (WINDOW_HEIGHT - __ly)) * ACCELEROMETER_FACTOR_Y;
+        __pitch -= -(float)(point.y - (__height - __ly)) * ACCELEROMETER_FACTOR_Y;
     
     
         // Clamp the values to the valid range.
         // Clamp the values to the valid range.
         __roll = max(min(__roll, 90.0f), -90.0f);
         __roll = max(min(__roll, 90.0f), -90.0f);
@@ -260,32 +279,32 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
     
     
         // Update the last X/Y values.
         // Update the last X/Y values.
         __lx = point.x;
         __lx = point.x;
-        __ly = (WINDOW_HEIGHT - point.y);
+        __ly = (__height - point.y);
     }
     }
     
     
     // In right-mouse case, whether __rightMouseDown is true or false
     // In right-mouse case, whether __rightMouseDown is true or false
     // this should not matter, mouse move is still occuring
     // this should not matter, mouse move is still occuring
-    _game->mouseEvent(Mouse::MOUSE_MOVE, point.x, WINDOW_HEIGHT - point.y, 0);
+    _game->mouseEvent(Mouse::MOUSE_MOVE, point.x, __height - point.y, 0);
 }
 }
 
 
 - (void)otherMouseDown: (NSEvent *) event 
 - (void)otherMouseDown: (NSEvent *) event 
 {
 {
     __otherMouseDown = true;
     __otherMouseDown = true;
     NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
     NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
-    _game->mouseEvent(Mouse::MOUSE_PRESS_MIDDLE_BUTTON, point.x, WINDOW_HEIGHT - point.y, 0);
+    _game->mouseEvent(Mouse::MOUSE_PRESS_MIDDLE_BUTTON, point.x, __height - point.y, 0);
 }
 }
 
 
 - (void)otherMouseUp: (NSEvent *) event 
 - (void)otherMouseUp: (NSEvent *) event 
 {
 {
     __otherMouseDown = false;
     __otherMouseDown = false;
     NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
     NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
-    _game->mouseEvent(Mouse::MOUSE_RELEASE_MIDDLE_BUTTON, point.x, WINDOW_HEIGHT - point.y, 0);
+    _game->mouseEvent(Mouse::MOUSE_RELEASE_MIDDLE_BUTTON, point.x, __height - point.y, 0);
 }
 }
 
 
 - (void)otherMouseDragged: (NSEvent *) event 
 - (void)otherMouseDragged: (NSEvent *) event 
 {
 {
     NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
     NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
-    _game->mouseEvent(Mouse::MOUSE_MOVE, point.x, WINDOW_HEIGHT - point.y, 0);
+    _game->mouseEvent(Mouse::MOUSE_MOVE, point.x, __height - point.y, 0);
 }
 }
 
 
 - (void) mouseEntered: (NSEvent*)event
 - (void) mouseEntered: (NSEvent*)event
@@ -296,7 +315,7 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
 - (void)scrollWheel: (NSEvent *) event 
 - (void)scrollWheel: (NSEvent *) event 
 {
 {
     NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
     NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
-    Game::getInstance()->mouseEvent(Mouse::MOUSE_WHEEL, point.x, WINDOW_HEIGHT - point.y, (int)([event deltaY] * 10.0f));
+    Game::getInstance()->mouseEvent(Mouse::MOUSE_WHEEL, point.x, __height - point.y, (int)([event deltaY] * 10.0f));
 }
 }
 
 
 - (void) mouseExited: (NSEvent*)event
 - (void) mouseExited: (NSEvent*)event
@@ -557,12 +576,25 @@ int getKey(unsigned short keyCode, unsigned int modifierFlags)
 
 
 @end
 @end
 
 
+@interface FullscreenWindow : NSWindow
+{ 
+}
+@end
+
+@implementation FullscreenWindow
+- (BOOL)canBecomeKeyWindow
+{
+    return YES;
+}
+@end
+
 
 
 namespace gameplay
 namespace gameplay
 {
 {
 
 
 extern void printError(const char* format, ...)
 extern void printError(const char* format, ...)
 {
 {
+    GP_ASSERT(format);
     va_list argptr;
     va_list argptr;
     va_start(argptr, format);
     va_start(argptr, format);
     vfprintf(stderr, format, argptr);
     vfprintf(stderr, format, argptr);
@@ -591,10 +623,40 @@ Platform* Platform::create(Game* game)
 
 
 int Platform::enterMessagePump()
 int Platform::enterMessagePump()
 {
 {
+    NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
+    NSString* path = [bundlePath stringByAppendingString:@"/Contents/Resources/"];
+    FileSystem::setResourcePath([path cStringUsingEncoding:NSASCIIStringEncoding]);
+    
+    // Read window settings from config.
+    if (_game->getConfig())
+    {
+        Properties* config = _game->getConfig()->getNamespace("window", true);
+        if (config)
+        {
+            // Read window title.
+            __title = const_cast<char *>(config->getString("title"));
+
+            // Read window size.
+            int width = config->getInt("width");
+            if (width != 0)
+                __width = width;
+            int height = config->getInt("height");
+            if (height != 0)
+                __height = height;
+
+            // Read fullscreen state.
+            __fullscreen = config->getBool("fullscreen");
+        }
+    }
+
+    // Set the scale factors for the mouse movement used to simulate the accelerometer.
+    ACCELEROMETER_FACTOR_X = 90.0f / __width;
+    ACCELEROMETER_FACTOR_Y = 90.0f / __height;
+
     NSAutoreleasePool* pool = [NSAutoreleasePool new];
     NSAutoreleasePool* pool = [NSAutoreleasePool new];
     NSApplication* app = [NSApplication sharedApplication];
     NSApplication* app = [NSApplication sharedApplication];
     NSRect screenBounds = [[NSScreen mainScreen] frame];
     NSRect screenBounds = [[NSScreen mainScreen] frame];
-    NSRect viewBounds = NSMakeRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
+    NSRect viewBounds = NSMakeRect(0, 0, __width, __height);
     
     
     __view = [[View alloc] initWithFrame:viewBounds];
     __view = [[View alloc] initWithFrame:viewBounds];
     
     
@@ -603,11 +665,23 @@ int Platform::enterMessagePump()
                                  viewBounds.size.width, 
                                  viewBounds.size.width, 
                                  viewBounds.size.height);
                                  viewBounds.size.height);
     
     
-    NSWindow* window = [[NSWindow alloc]
-                        initWithContentRect:centered
-                        styleMask:NSTitledWindowMask | NSClosableWindowMask
-                        backing:NSBackingStoreBuffered
-                        defer:NO];
+    NSWindow* window = NULL;
+    if (__fullscreen)
+    {
+        window = [[FullscreenWindow alloc]
+                   initWithContentRect:screenBounds
+                   styleMask:NSBorderlessWindowMask
+                   backing:NSBackingStoreBuffered
+                   defer:NO];
+    }
+    else
+    {
+        window = [[NSWindow alloc]
+                   initWithContentRect:centered
+                   styleMask:NSTitledWindowMask | NSClosableWindowMask
+                   backing:NSBackingStoreBuffered
+                   defer:NO];
+    }
     
     
     [window setAcceptsMouseMovedEvents:YES];
     [window setAcceptsMouseMovedEvents:YES];
     [window setContentView:__view];
     [window setContentView:__view];
@@ -632,12 +706,12 @@ void Platform::signalShutdown()
     
     
 unsigned int Platform::getDisplayWidth()
 unsigned int Platform::getDisplayWidth()
 {
 {
-    return WINDOW_WIDTH;
+    return __width;
 }
 }
 
 
 unsigned int Platform::getDisplayHeight()
 unsigned int Platform::getDisplayHeight()
 {
 {
-    return WINDOW_HEIGHT;
+    return __height;
 }
 }
 
 
 long Platform::getAbsoluteTime()
 long Platform::getAbsoluteTime()
@@ -672,6 +746,9 @@ bool Platform::isMultiTouch()
     
     
 void Platform::getAccelerometerValues(float* pitch, float* roll)
 void Platform::getAccelerometerValues(float* pitch, float* roll)
 {
 {
+    GP_ASSERT(pitch);
+    GP_ASSERT(roll);
+
     *pitch = __pitch;
     *pitch = __pitch;
     *roll = __roll;
     *roll = __roll;
 }
 }
@@ -697,7 +774,7 @@ void Platform::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned
     
     
 void Platform::keyEventInternal(Keyboard::KeyEvent evt, int key)
 void Platform::keyEventInternal(Keyboard::KeyEvent evt, int key)
 {
 {
-    gameplay::Game::getInstance()->keyEvent(evt, key);
+    Game::getInstance()->keyEvent(evt, key);
     Form::keyEventInternal(evt, key);
     Form::keyEventInternal(evt, key);
 }
 }
     
     

+ 14 - 6
gameplay/src/PlatformQNX.cpp

@@ -401,6 +401,7 @@ static int getUnicode(int qnxKeyCode)
 
 
 extern void printError(const char* format, ...)
 extern void printError(const char* format, ...)
 {
 {
+    GP_ASSERT(format);
     va_list argptr;
     va_list argptr;
     va_start(argptr, format);
     va_start(argptr, format);
     vfprintf(stderr, format, argptr);
     vfprintf(stderr, format, argptr);
@@ -409,6 +410,7 @@ extern void printError(const char* format, ...)
 
 
 EGLenum checkErrorEGL(const char* msg)
 EGLenum checkErrorEGL(const char* msg)
 {
 {
+    GP_ASSERT(msg);
     static const char* errmsg[] =
     static const char* errmsg[] =
     {
     {
         "EGL function succeeded",
         "EGL function succeeded",
@@ -751,6 +753,7 @@ error:
  */
  */
 long timespec2millis(struct timespec *a)
 long timespec2millis(struct timespec *a)
 {
 {
+    GP_ASSERT(a);
     return a->tv_sec*1000 + a->tv_nsec/1000000;
     return a->tv_sec*1000 + a->tv_nsec/1000000;
 }
 }
 
 
@@ -773,6 +776,8 @@ void mouseOrTouchEvent(Mouse::MouseEvent mouseEvent, Touch::TouchEvent touchEven
 
 
 int Platform::enterMessagePump()
 int Platform::enterMessagePump()
 {
 {
+    GP_ASSERT(_game);
+
     int rc;
     int rc;
     int eventType;
     int eventType;
     int flags;
     int flags;
@@ -849,7 +854,7 @@ int Platform::enterMessagePump()
                         // A move event will be fired unless a button state changed.
                         // A move event will be fired unless a button state changed.
                         bool move = true;
                         bool move = true;
                         bool left_move = false;
                         bool left_move = false;
-                        //This is a mouse move event, it is applicable to a device with a usb mouse or simulator
+                        // This is a mouse move event, it is applicable to a device with a usb mouse or simulator.
                         screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_BUTTONS, &buttons);
                         screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_BUTTONS, &buttons);
                         screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_SOURCE_POSITION, position);
                         screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_SOURCE_POSITION, position);
                         screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_MOUSE_WHEEL, &wheel);
                         screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_MOUSE_WHEEL, &wheel);
@@ -875,7 +880,7 @@ int Platform::enterMessagePump()
                             mouseOrTouchEvent(Mouse::MOUSE_RELEASE_LEFT_BUTTON, Touch::TOUCH_RELEASE, position[0], position[1]);
                             mouseOrTouchEvent(Mouse::MOUSE_RELEASE_LEFT_BUTTON, Touch::TOUCH_RELEASE, position[0], position[1]);
                         }
                         }
 
 
-                        // Handle right mouse
+                        // Handle right mouse.
                         if (buttons & SCREEN_RIGHT_MOUSE_BUTTON)
                         if (buttons & SCREEN_RIGHT_MOUSE_BUTTON)
                         {
                         {
                             if ((mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON) == 0)
                             if ((mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON) == 0)
@@ -892,7 +897,7 @@ int Platform::enterMessagePump()
                             Game::getInstance()->mouseEvent(Mouse::MOUSE_RELEASE_RIGHT_BUTTON, position[0], position[1], 0);
                             Game::getInstance()->mouseEvent(Mouse::MOUSE_RELEASE_RIGHT_BUTTON, position[0], position[1], 0);
                         }
                         }
 
 
-                        // Handle middle mouse
+                        // Handle middle mouse.
                         if (buttons & SCREEN_MIDDLE_MOUSE_BUTTON)
                         if (buttons & SCREEN_MIDDLE_MOUSE_BUTTON)
                         {
                         {
                             if ((mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON) == 0)
                             if ((mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON) == 0)
@@ -919,7 +924,7 @@ int Platform::enterMessagePump()
                             Game::getInstance()->mouseEvent(Mouse::MOUSE_MOVE, position[0], position[1], 0);
                             Game::getInstance()->mouseEvent(Mouse::MOUSE_MOVE, position[0], position[1], 0);
                         }
                         }
 
 
-                        // Handle mouse wheel events
+                        // Handle mouse wheel events.
                         if (wheel)
                         if (wheel)
                         {
                         {
                             Game::getInstance()->mouseEvent(Mouse::MOUSE_WHEEL, position[0], position[1], -wheel);
                             Game::getInstance()->mouseEvent(Mouse::MOUSE_WHEEL, position[0], position[1], -wheel);
@@ -932,7 +937,7 @@ int Platform::enterMessagePump()
                         screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_KEY_FLAGS, &flags);
                         screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_KEY_FLAGS, &flags);
                         screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_KEY_SYM, &value);
                         screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_KEY_SYM, &value);
                         gameplay::Keyboard::KeyEvent evt = (flags & KEY_DOWN) ? gameplay::Keyboard::KEY_PRESS :  gameplay::Keyboard::KEY_RELEASE;
                         gameplay::Keyboard::KeyEvent evt = (flags & KEY_DOWN) ? gameplay::Keyboard::KEY_PRESS :  gameplay::Keyboard::KEY_RELEASE;
-                        // Suppress key repeats
+                        // Suppress key repeats.
                         if ((flags & KEY_REPEAT) == 0)
                         if ((flags & KEY_REPEAT) == 0)
                         {
                         {
                             keyEventInternal(evt, getKey(value));
                             keyEventInternal(evt, getKey(value));
@@ -1076,6 +1081,9 @@ bool Platform::isMultiTouch()
 
 
 void Platform::getAccelerometerValues(float* pitch, float* roll)
 void Platform::getAccelerometerValues(float* pitch, float* roll)
 {
 {
+    GP_ASSERT(pitch);
+    GP_ASSERT(roll);
+
     switch(__orientationAngle)
     switch(__orientationAngle)
     {
     {
     // Landscape based device adjusting for landscape game mode
     // Landscape based device adjusting for landscape game mode
@@ -1136,7 +1144,7 @@ void Platform::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned
 
 
 void Platform::keyEventInternal(Keyboard::KeyEvent evt, int key)
 void Platform::keyEventInternal(Keyboard::KeyEvent evt, int key)
 {
 {
-    gameplay::Game::getInstance()->keyEvent(evt, key);
+    Game::getInstance()->keyEvent(evt, key);
     Form::keyEventInternal(evt, key);
     Form::keyEventInternal(evt, key);
 }
 }
 
 

+ 67 - 33
gameplay/src/PlatformWin32.cpp

@@ -8,6 +8,8 @@
 #include <GL/wglew.h>
 #include <GL/wglew.h>
 #include <windowsx.h>
 #include <windowsx.h>
 
 
+using gameplay::printError;
+
 // Default to 720p
 // Default to 720p
 static int __width = 1280;
 static int __width = 1280;
 static int __height = 720;
 static int __height = 720;
@@ -257,11 +259,13 @@ LRESULT CALLBACK __WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
 {
     if (hwnd != __hwnd)
     if (hwnd != __hwnd)
     {
     {
-        // Ignore messages that are not for our game window
-        return DefWindowProc(hwnd, msg, wParam, lParam); 
+        // Ignore messages that are not for our game window.
+        return DefWindowProc(hwnd, msg, wParam, lParam);
     }
     }
 
 
     // Scale factors for the mouse movement used to simulate the accelerometer.
     // Scale factors for the mouse movement used to simulate the accelerometer.
+    GP_ASSERT(__width);
+    GP_ASSERT(__height);
     static const float ACCELEROMETER_X_FACTOR = 90.0f / __width;
     static const float ACCELEROMETER_X_FACTOR = 90.0f / __width;
     static const float ACCELEROMETER_Y_FACTOR = 90.0f / __height;
     static const float ACCELEROMETER_Y_FACTOR = 90.0f / __height;
 
 
@@ -374,7 +378,7 @@ LRESULT CALLBACK __WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
         if (wParam == VK_CAPITAL)
         if (wParam == VK_CAPITAL)
             capsOn = !capsOn;
             capsOn = !capsOn;
 
 
-        // Suppress key repeats
+        // Suppress key repeats.
         if ((lParam & 0x40000000) == 0)
         if ((lParam & 0x40000000) == 0)
             gameplay::Platform::keyEventInternal(gameplay::Keyboard::KEY_PRESS, getKey(wParam, shiftDown ^ capsOn));
             gameplay::Platform::keyEventInternal(gameplay::Keyboard::KEY_PRESS, getKey(wParam, shiftDown ^ capsOn));
         break;
         break;
@@ -387,13 +391,13 @@ LRESULT CALLBACK __WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
         break;
         break;
 
 
     case WM_CHAR:
     case WM_CHAR:
-        // Suppress key repeats
+        // Suppress key repeats.
         if ((lParam & 0x40000000) == 0)
         if ((lParam & 0x40000000) == 0)
             gameplay::Platform::keyEventInternal(gameplay::Keyboard::KEY_CHAR, wParam);
             gameplay::Platform::keyEventInternal(gameplay::Keyboard::KEY_CHAR, wParam);
         break;
         break;
 
 
     case WM_UNICHAR:
     case WM_UNICHAR:
-        // Suppress key repeats
+        // Suppress key repeats.
         if ((lParam & 0x40000000) == 0)
         if ((lParam & 0x40000000) == 0)
             gameplay::Platform::keyEventInternal(gameplay::Keyboard::KEY_CHAR, wParam);
             gameplay::Platform::keyEventInternal(gameplay::Keyboard::KEY_CHAR, wParam);
         break;
         break;
@@ -449,6 +453,8 @@ Platform::~Platform()
 
 
 Platform* Platform::create(Game* game)
 Platform* Platform::create(Game* game)
 {
 {
+    GP_ASSERT(game);
+
     FileSystem::setResourcePath("./");
     FileSystem::setResourcePath("./");
 
 
     Platform* platform = new Platform(game);
     Platform* platform = new Platform(game);
@@ -460,31 +466,34 @@ Platform* Platform::create(Game* game)
     std::wstring windowName;
     std::wstring windowName;
     bool fullscreen = false;
     bool fullscreen = false;
     
     
-    // Read window settings from config
-    Properties* config = game->getConfig()->getNamespace("window", true);
-    if (config)
+    // Read window settings from config.
+    if (game->getConfig())
     {
     {
-        // Read window title
-        const char* title = config->getString("title");
-        if (title)
+        Properties* config = game->getConfig()->getNamespace("window", true);
+        if (config)
         {
         {
-            int len = MultiByteToWideChar(CP_ACP, 0, title, -1, NULL, 0);
-            wchar_t* wtitle = new wchar_t[len];
-            MultiByteToWideChar(CP_ACP, 0, title, -1, wtitle, len);
-            windowName = wtitle;
-            SAFE_DELETE_ARRAY(wtitle);
-        }
+            // Read window title.
+            const char* title = config->getString("title");
+            if (title)
+            {
+                int len = MultiByteToWideChar(CP_ACP, 0, title, -1, NULL, 0);
+                wchar_t* wtitle = new wchar_t[len];
+                MultiByteToWideChar(CP_ACP, 0, title, -1, wtitle, len);
+                windowName = wtitle;
+                SAFE_DELETE_ARRAY(wtitle);
+            }
 
 
-        // Read window size
-        int width = config->getInt("width");
-        if (width != 0)
-            __width = width;
-        int height = config->getInt("height");
-        if (height != 0)
-            __height = height;
+            // Read window size.
+            int width = config->getInt("width");
+            if (width != 0)
+                __width = width;
+            int height = config->getInt("height");
+            if (height != 0)
+                __height = height;
 
 
-        // Read fullscreen state
-        fullscreen = config->getBool("fullscreen");
+            // Read fullscreen state.
+            fullscreen = config->getBool("fullscreen");
+        }
     }
     }
 
 
     RECT rect = { 0, 0, __width, __height };
     RECT rect = { 0, 0, __width, __height };
@@ -505,7 +514,10 @@ Platform* Platform::create(Game* game)
     wc.lpszClassName  = windowClass;
     wc.lpszClassName  = windowClass;
 
 
     if (!::RegisterClassEx(&wc))
     if (!::RegisterClassEx(&wc))
+    {
+        GP_ERROR("Failed to register window class.");
         goto error;
         goto error;
+    }
 
 
     if (fullscreen)
     if (fullscreen)
     {
     {
@@ -517,11 +529,12 @@ Platform* Platform::create(Game* game)
         dm.dmBitsPerPel	= 32;
         dm.dmBitsPerPel	= 32;
         dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
         dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
 
 
-        // Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
+        // Try to set selected mode and get results. NOTE: CDS_FULLSCREEN gets rid of start bar.
         if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
         if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
         {
         {
             fullscreen = false;
             fullscreen = false;
-            GP_ERROR("Failed to start fullscreen with resolution %dx%d.", __width, __height);
+            GP_ERROR("Failed to start game in full-screen mode with resolution %dx%d.", __width, __height);
+            goto error;
         }
         }
     }
     }
 
 
@@ -557,14 +570,25 @@ Platform* Platform::create(Game* game)
 
 
     int pixelFormat = ChoosePixelFormat(__hdc, &pfd);
     int pixelFormat = ChoosePixelFormat(__hdc, &pfd);
 
 
-    if (pixelFormat == 0 || !SetPixelFormat (__hdc, pixelFormat, &pfd))
+    if (pixelFormat == 0)
+    {
+        GP_ERROR("Failed to choose a pixel format.");
+        goto error;
+    }
+    if (!SetPixelFormat (__hdc, pixelFormat, &pfd))
+    {
+        GP_ERROR("Failed to set the pixel format.");
         goto error;
         goto error;
+    }
 
 
     HGLRC tempContext = wglCreateContext(__hdc);
     HGLRC tempContext = wglCreateContext(__hdc);
     wglMakeCurrent(__hdc, tempContext);
     wglMakeCurrent(__hdc, tempContext);
 
 
     if (GLEW_OK != glewInit())
     if (GLEW_OK != glewInit())
+    {
+        GP_ERROR("Failed to initialize GLEW.");
         goto error;
         goto error;
+    }
 
 
     int attribs[] =
     int attribs[] =
     {
     {
@@ -576,17 +600,21 @@ Platform* Platform::create(Game* game)
     if (!(__hrc = wglCreateContextAttribsARB(__hdc, 0, attribs) ) )
     if (!(__hrc = wglCreateContextAttribsARB(__hdc, 0, attribs) ) )
     {
     {
         wglDeleteContext(tempContext);
         wglDeleteContext(tempContext);
+        GP_ERROR("Failed to create OpenGL context.");
         goto error;
         goto error;
     }
     }
     wglDeleteContext(tempContext);
     wglDeleteContext(tempContext);
 
 
     if (!wglMakeCurrent(__hdc, __hrc) || !__hrc)
     if (!wglMakeCurrent(__hdc, __hrc) || !__hrc)
+    {
+        GP_ERROR("Failed to make the window current.");
         goto error;
         goto error;
+    }
 
 
     // Vertical sync.
     // Vertical sync.
     wglSwapIntervalEXT(__vsync ? 1 : 0);
     wglSwapIntervalEXT(__vsync ? 1 : 0);
 
 
-    // Show the window
+    // Show the window.
     ShowWindow(__hwnd, SW_SHOW);
     ShowWindow(__hwnd, SW_SHOW);
 
 
     return platform;
     return platform;
@@ -598,7 +626,8 @@ error:
 }
 }
 
 
 int Platform::enterMessagePump()
 int Platform::enterMessagePump()
-{  
+{
+    GP_ASSERT(_game);
     int rc = 0;
     int rc = 0;
 
 
     // Get the initial time.
     // Get the initial time.
@@ -607,6 +636,7 @@ int Platform::enterMessagePump()
     __timeTicksPerMillis = (long)(tps.QuadPart / 1000L);
     __timeTicksPerMillis = (long)(tps.QuadPart / 1000L);
     LARGE_INTEGER queryTime;
     LARGE_INTEGER queryTime;
     QueryPerformanceCounter(&queryTime);
     QueryPerformanceCounter(&queryTime);
+    GP_ASSERT(__timeTicksPerMillis);
     __timeStart = queryTime.QuadPart / __timeTicksPerMillis;
     __timeStart = queryTime.QuadPart / __timeTicksPerMillis;
 
 
     // Set the initial pitch and roll values.
     // Set the initial pitch and roll values.
@@ -659,8 +689,9 @@ unsigned int Platform::getDisplayHeight()
     
     
 long Platform::getAbsoluteTime()
 long Platform::getAbsoluteTime()
 {
 {
-       LARGE_INTEGER queryTime;
+    LARGE_INTEGER queryTime;
     QueryPerformanceCounter(&queryTime);
     QueryPerformanceCounter(&queryTime);
+    GP_ASSERT(__timeTicksPerMillis);
     __timeAbsolute = queryTime.QuadPart / __timeTicksPerMillis;
     __timeAbsolute = queryTime.QuadPart / __timeTicksPerMillis;
 
 
     return __timeAbsolute;
     return __timeAbsolute;
@@ -693,6 +724,9 @@ bool Platform::isMultiTouch()
 
 
 void Platform::getAccelerometerValues(float* pitch, float* roll)
 void Platform::getAccelerometerValues(float* pitch, float* roll)
 {
 {
+    GP_ASSERT(pitch);
+    GP_ASSERT(roll);
+
     *pitch = __pitch;
     *pitch = __pitch;
     *roll = __roll;
     *roll = __roll;
 }
 }
@@ -718,7 +752,7 @@ void Platform::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned
 
 
 void Platform::keyEventInternal(Keyboard::KeyEvent evt, int key)
 void Platform::keyEventInternal(Keyboard::KeyEvent evt, int key)
 {
 {
-    gameplay::Game::getInstance()->keyEvent(evt, key);
+    Game::getInstance()->keyEvent(evt, key);
     Form::keyEventInternal(evt, key);
     Form::keyEventInternal(evt, key);
 }
 }
 
 

+ 3 - 1
gameplay/src/PlatformiOS.mm

@@ -549,6 +549,7 @@ long getMachTimeInMilliseconds()
         (void) mach_timebase_info(&s_timebase_info);
         (void) mach_timebase_info(&s_timebase_info);
     
     
     // mach_absolute_time() returns billionth of seconds, so divide by one million to get milliseconds
     // mach_absolute_time() returns billionth of seconds, so divide by one million to get milliseconds
+    GP_ASSERT(kOneMillion * s_timebase_info.denom);
     return (long)((mach_absolute_time() * s_timebase_info.numer) / (kOneMillion * s_timebase_info.denom));
     return (long)((mach_absolute_time() * s_timebase_info.numer) / (kOneMillion * s_timebase_info.denom));
 }
 }
 
 
@@ -773,6 +774,7 @@ namespace gameplay
     
     
 extern void printError(const char* format, ...)
 extern void printError(const char* format, ...)
 {
 {
+    GP_ASSERT(format);
     va_list argptr;
     va_list argptr;
     va_start(argptr, format);
     va_start(argptr, format);
     vfprintf(stderr, format, argptr);
     vfprintf(stderr, format, argptr);
@@ -891,7 +893,7 @@ void Platform::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned
 
 
 void Platform::keyEventInternal(Keyboard::KeyEvent evt, int key)
 void Platform::keyEventInternal(Keyboard::KeyEvent evt, int key)
 {
 {
-    gameplay::Game::getInstance()->keyEvent(evt, key);
+    Game::getInstance()->keyEvent(evt, key);
     Form::keyEventInternal(evt, key);
     Form::keyEventInternal(evt, key);
 }
 }
     
     

+ 11 - 2
gameplay/src/Ref.cpp

@@ -76,6 +76,7 @@ void Ref::printLeaks()
         for (RefAllocationRecord* rec = __refAllocations; rec != NULL; rec = rec->next)
         for (RefAllocationRecord* rec = __refAllocations; rec != NULL; rec = rec->next)
         {
         {
             Ref* ref = rec->ref;
             Ref* ref = rec->ref;
+            GP_ASSERT(ref);
             const char* type = typeid(*ref).name();
             const char* type = typeid(*ref).name();
             printError("[memory] LEAK: Ref object '%s' still active with reference count %d.\n", (type ? type : ""), ref->getRefCount());
             printError("[memory] LEAK: Ref object '%s' still active with reference count %d.\n", (type ? type : ""), ref->getRefCount());
         }
         }
@@ -84,7 +85,9 @@ void Ref::printLeaks()
 
 
 void* trackRef(Ref* ref)
 void* trackRef(Ref* ref)
 {
 {
-    // Create memory allocation record
+    GP_ASSERT(ref);
+
+    // Create memory allocation record.
     RefAllocationRecord* rec = (RefAllocationRecord*)malloc(sizeof(RefAllocationRecord));
     RefAllocationRecord* rec = (RefAllocationRecord*)malloc(sizeof(RefAllocationRecord));
     rec->ref = ref;
     rec->ref = ref;
     rec->next = __refAllocations;
     rec->next = __refAllocations;
@@ -100,6 +103,12 @@ void* trackRef(Ref* ref)
 
 
 void untrackRef(Ref* ref, void* record)
 void untrackRef(Ref* ref, void* record)
 {
 {
+    if (!record)
+    {
+        printError("[memory] ERROR: Attempting to free null ref tracking record.\n");
+        return;
+    }
+
     RefAllocationRecord* rec = (RefAllocationRecord*)record;
     RefAllocationRecord* rec = (RefAllocationRecord*)record;
     if (rec->ref != ref)
     if (rec->ref != ref)
     {
     {
@@ -107,7 +116,7 @@ void untrackRef(Ref* ref, void* record)
         return;
         return;
     }
     }
 
 
-    // Link this item out
+    // Link this item out.
     if (__refAllocations == rec)
     if (__refAllocations == rec)
         __refAllocations = rec->next;
         __refAllocations = rec->next;
     if (rec->prev)
     if (rec->prev)

+ 3 - 3
gameplay/src/RenderState.cpp

@@ -399,7 +399,7 @@ void RenderState::StateBlock::bindNoRestore()
     if ((_bits & RS_BLEND) && (_blendEnabled != _defaultState->_blendEnabled))
     if ((_bits & RS_BLEND) && (_blendEnabled != _defaultState->_blendEnabled))
     {
     {
         if (_blendEnabled)
         if (_blendEnabled)
-            GL_ASSERT( glEnable(GL_BLEND) )
+            GL_ASSERT( glEnable(GL_BLEND) );
         else
         else
             GL_ASSERT( glDisable(GL_BLEND) );
             GL_ASSERT( glDisable(GL_BLEND) );
         _defaultState->_blendEnabled = _blendEnabled;
         _defaultState->_blendEnabled = _blendEnabled;
@@ -413,7 +413,7 @@ void RenderState::StateBlock::bindNoRestore()
     if ((_bits & RS_CULL_FACE) && (_cullFaceEnabled != _defaultState->_cullFaceEnabled))
     if ((_bits & RS_CULL_FACE) && (_cullFaceEnabled != _defaultState->_cullFaceEnabled))
     {
     {
         if (_cullFaceEnabled)
         if (_cullFaceEnabled)
-            GL_ASSERT( glEnable(GL_CULL_FACE) ) 
+            GL_ASSERT( glEnable(GL_CULL_FACE) );
         else
         else
             GL_ASSERT( glDisable(GL_CULL_FACE) );
             GL_ASSERT( glDisable(GL_CULL_FACE) );
         _defaultState->_cullFaceEnabled = _cullFaceEnabled;
         _defaultState->_cullFaceEnabled = _cullFaceEnabled;
@@ -421,7 +421,7 @@ void RenderState::StateBlock::bindNoRestore()
     if ((_bits & RS_DEPTH_TEST) && (_depthTestEnabled != _defaultState->_depthTestEnabled))
     if ((_bits & RS_DEPTH_TEST) && (_depthTestEnabled != _defaultState->_depthTestEnabled))
     {
     {
         if (_depthTestEnabled) 
         if (_depthTestEnabled) 
-            GL_ASSERT( glEnable(GL_DEPTH_TEST) ) 
+            GL_ASSERT( glEnable(GL_DEPTH_TEST) );
         else 
         else 
             GL_ASSERT( glDisable(GL_DEPTH_TEST) );
             GL_ASSERT( glDisable(GL_DEPTH_TEST) );
         _defaultState->_depthTestEnabled = _depthTestEnabled;
         _defaultState->_depthTestEnabled = _depthTestEnabled;

+ 1 - 1
gameplay/src/gameplay-main-android.cpp

@@ -18,8 +18,8 @@ void android_main(struct android_app* state)
     
     
     __state = state;
     __state = state;
     Game* game = Game::getInstance();
     Game* game = Game::getInstance();
-    GP_ASSERT(game != NULL);
     Platform* platform = Platform::create(game);
     Platform* platform = Platform::create(game);
+    GP_ASSERT(platform);
     platform->enterMessagePump();
     platform->enterMessagePump();
     delete platform;
     delete platform;
     
     

+ 1 - 1
gameplay/src/gameplay-main-ios.mm

@@ -10,8 +10,8 @@ using namespace gameplay;
 int main(int argc, char** argv)
 int main(int argc, char** argv)
 {    
 {    
     Game* game = Game::getInstance();
     Game* game = Game::getInstance();
-    GP_ASSERT(game != NULL);
     Platform* platform = Platform::create(game);
     Platform* platform = Platform::create(game);
+    GP_ASSERT(platform);
     int result = platform->enterMessagePump();
     int result = platform->enterMessagePump();
 	delete platform;
 	delete platform;
     return result;
     return result;

+ 1 - 1
gameplay/src/gameplay-main-macosx.mm

@@ -10,8 +10,8 @@ using namespace gameplay;
 int main(int argc, char** argv)
 int main(int argc, char** argv)
 {
 {
     Game* game = Game::getInstance();
     Game* game = Game::getInstance();
-    GP_ASSERT(game != NULL);
     Platform* platform = Platform::create(game);
     Platform* platform = Platform::create(game);
+    GP_ASSERT(platform);
     int result = platform->enterMessagePump();
     int result = platform->enterMessagePump();
 	delete platform;
 	delete platform;
     return result;
     return result;

+ 1 - 1
gameplay/src/gameplay-main-qnx.cpp

@@ -10,8 +10,8 @@ using namespace gameplay;
 int main(int argc, char** argv)
 int main(int argc, char** argv)
 {
 {
     Game* game = Game::getInstance();
     Game* game = Game::getInstance();
-    GP_ASSERT(game != NULL);
     Platform* platform = Platform::create(game);
     Platform* platform = Platform::create(game);
+    GP_ASSERT(platform);
     int result = platform->enterMessagePump();
     int result = platform->enterMessagePump();
     delete platform;
     delete platform;
     return result;
     return result;

+ 1 - 1
gameplay/src/gameplay-main-win32.cpp

@@ -15,8 +15,8 @@ using namespace gameplay;
 extern "C" int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow)
 extern "C" int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow)
 {
 {
     Game* game = Game::getInstance();
     Game* game = Game::getInstance();
-    GP_ASSERT(game != NULL);
     Platform* platform = Platform::create(game);
     Platform* platform = Platform::create(game);
+    GP_ASSERT(platform);
     int result = platform->enterMessagePump();
     int result = platform->enterMessagePump();
     delete platform;
     delete platform;
     return result;
     return result;