diff --git a/Chipmunk2D-7.0.2/include/chipmunk/chipmunk.h b/Chipmunk2D-7.0.2/include/chipmunk/chipmunk.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/chipmunk.h
@@ -0,0 +1,232 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef CHIPMUNK_H
+#define CHIPMUNK_H
+
+#include <stdlib.h>
+#include <math.h>
+
+#ifndef alloca
+	#ifdef _WIN32
+		#include <malloc.h>
+	#elif defined(__FreeBSD__)
+		/* already included in <stdlib.h> */
+	#else
+		#include <alloca.h>
+	#endif
+#endif
+
+#ifdef _WIN32
+	#define CP_EXPORT __declspec(dllexport)
+#else
+	#define CP_EXPORT
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CP_EXPORT void cpMessage(const char *condition, const char *file, int line, int isError, int isHardError, const char *message, ...);
+#ifdef NDEBUG
+	#define	cpAssertWarn(__condition__, ...)
+	#define	cpAssertSoft(__condition__, ...)
+#else
+	#define cpAssertSoft(__condition__, ...) if(!(__condition__)){cpMessage(#__condition__, __FILE__, __LINE__, 1, 0, __VA_ARGS__); abort();}
+	#define cpAssertWarn(__condition__, ...) if(!(__condition__)) cpMessage(#__condition__, __FILE__, __LINE__, 0, 0, __VA_ARGS__)
+#endif
+
+// Hard assertions are used in situations where the program definitely will crash anyway, and the reason is inexpensive to detect.
+#define cpAssertHard(__condition__, ...) if(!(__condition__)){cpMessage(#__condition__, __FILE__, __LINE__, 1, 1, __VA_ARGS__); abort();}
+
+#include "chipmunk_types.h"
+	
+/// @defgroup misc Misc
+/// @{
+
+/// Allocated size for various Chipmunk buffers
+#ifndef CP_BUFFER_BYTES
+	#define CP_BUFFER_BYTES (32*1024)
+#endif
+
+#ifndef cpcalloc
+	/// Chipmunk calloc() alias.
+	#define cpcalloc calloc
+#endif
+
+#ifndef cprealloc
+	/// Chipmunk realloc() alias.
+	#define cprealloc realloc
+#endif
+
+#ifndef cpfree
+	/// Chipmunk free() alias.
+	#define cpfree free
+#endif
+
+typedef struct cpArray cpArray;
+typedef struct cpHashSet cpHashSet;
+
+typedef struct cpBody cpBody;
+
+typedef struct cpShape cpShape;
+typedef struct cpCircleShape cpCircleShape;
+typedef struct cpSegmentShape cpSegmentShape;
+typedef struct cpPolyShape cpPolyShape;
+
+typedef struct cpConstraint cpConstraint;
+typedef struct cpPinJoint cpPinJoint;
+typedef struct cpSlideJoint cpSlideJoint;
+typedef struct cpPivotJoint cpPivotJoint;
+typedef struct cpGrooveJoint cpGrooveJoint;
+typedef struct cpDampedSpring cpDampedSpring;
+typedef struct cpDampedRotarySpring cpDampedRotarySpring;
+typedef struct cpRotaryLimitJoint cpRotaryLimitJoint;
+typedef struct cpRatchetJoint cpRatchetJoint;
+typedef struct cpGearJoint cpGearJoint;
+typedef struct cpSimpleMotorJoint cpSimpleMotorJoint;
+
+typedef struct cpCollisionHandler cpCollisionHandler;
+typedef struct cpContactPointSet cpContactPointSet;
+typedef struct cpArbiter cpArbiter;
+
+typedef struct cpSpace cpSpace;
+
+#include "cpVect.h"
+#include "cpBB.h"
+#include "cpTransform.h"
+#include "cpSpatialIndex.h"
+
+#include "cpArbiter.h"	
+
+#include "cpBody.h"
+#include "cpShape.h"
+#include "cpPolyShape.h"
+
+#include "cpConstraint.h"
+
+#include "cpSpace.h"
+
+// Chipmunk 7.0.2
+#define CP_VERSION_MAJOR 7
+#define CP_VERSION_MINOR 0
+#define CP_VERSION_RELEASE 2
+
+/// Version string.
+CP_EXPORT extern const char *cpVersionString;
+
+/// Calculate the moment of inertia for a circle.
+/// @c r1 and @c r2 are the inner and outer diameters. A solid circle has an inner diameter of 0.
+CP_EXPORT cpFloat cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset);
+
+/// Calculate area of a hollow circle.
+/// @c r1 and @c r2 are the inner and outer diameters. A solid circle has an inner diameter of 0.
+CP_EXPORT cpFloat cpAreaForCircle(cpFloat r1, cpFloat r2);
+
+/// Calculate the moment of inertia for a line segment.
+/// Beveling radius is not supported.
+CP_EXPORT cpFloat cpMomentForSegment(cpFloat m, cpVect a, cpVect b, cpFloat radius);
+
+/// Calculate the area of a fattened (capsule shaped) line segment.
+CP_EXPORT cpFloat cpAreaForSegment(cpVect a, cpVect b, cpFloat radius);
+
+/// Calculate the moment of inertia for a solid polygon shape assuming it's center of gravity is at it's centroid. The offset is added to each vertex.
+CP_EXPORT cpFloat cpMomentForPoly(cpFloat m, int count, const cpVect *verts, cpVect offset, cpFloat radius);
+
+/// Calculate the signed area of a polygon. A Clockwise winding gives positive area.
+/// This is probably backwards from what you expect, but matches Chipmunk's the winding for poly shapes.
+CP_EXPORT cpFloat cpAreaForPoly(const int count, const cpVect *verts, cpFloat radius);
+
+/// Calculate the natural centroid of a polygon.
+CP_EXPORT cpVect cpCentroidForPoly(const int count, const cpVect *verts);
+
+/// Calculate the moment of inertia for a solid box.
+CP_EXPORT cpFloat cpMomentForBox(cpFloat m, cpFloat width, cpFloat height);
+
+/// Calculate the moment of inertia for a solid box.
+CP_EXPORT cpFloat cpMomentForBox2(cpFloat m, cpBB box);
+
+/// Calculate the convex hull of a given set of points. Returns the count of points in the hull.
+/// @c result must be a pointer to a @c cpVect array with at least @c count elements. If @c verts == @c result, then @c verts will be reduced inplace.
+/// @c first is an optional pointer to an integer to store where the first vertex in the hull came from (i.e. verts[first] == result[0])
+/// @c tol is the allowed amount to shrink the hull when simplifying it. A tolerance of 0.0 creates an exact hull.
+CP_EXPORT int cpConvexHull(int count, const cpVect *verts, cpVect *result, int *first, cpFloat tol);
+
+/// Convenience macro to work with cpConvexHull.
+/// @c count and @c verts is the input array passed to cpConvexHull().
+/// @c count_var and @c verts_var are the names of the variables the macro creates to store the result.
+/// The output vertex array is allocated on the stack using alloca() so it will be freed automatically, but cannot be returned from the current scope.
+#define CP_CONVEX_HULL(__count__, __verts__, __count_var__, __verts_var__) \
+cpVect *__verts_var__ = (cpVect *)alloca(__count__*sizeof(cpVect)); \
+int __count_var__ = cpConvexHull(__count__, __verts__, __verts_var__, NULL, 0.0); \
+
+/// Returns the closest point on the line segment ab, to the point p.
+static inline cpVect
+cpClosetPointOnSegment(const cpVect p, const cpVect a, const cpVect b)
+{
+	cpVect delta = cpvsub(a, b);
+	cpFloat t = cpfclamp01(cpvdot(delta, cpvsub(p, b))/cpvlengthsq(delta));
+	return cpvadd(b, cpvmult(delta, t));
+}
+
+#if defined(__has_extension)
+#if __has_extension(blocks)
+// Define alternate block based alternatives for a few of the callback heavy functions.
+// Collision handlers are post-step callbacks are not included to avoid memory management issues.
+// If you want to use blocks for those and are aware of how to correctly manage the memory, the implementation is trivial. 
+
+void cpSpaceEachBody_b(cpSpace *space, void (^block)(cpBody *body));
+void cpSpaceEachShape_b(cpSpace *space, void (^block)(cpShape *shape));
+void cpSpaceEachConstraint_b(cpSpace *space, void (^block)(cpConstraint *constraint));
+
+void cpBodyEachShape_b(cpBody *body, void (^block)(cpShape *shape));
+void cpBodyEachConstraint_b(cpBody *body, void (^block)(cpConstraint *constraint));
+void cpBodyEachArbiter_b(cpBody *body, void (^block)(cpArbiter *arbiter));
+
+typedef void (^cpSpacePointQueryBlock)(cpShape *shape, cpVect point, cpFloat distance, cpVect gradient);
+void cpSpacePointQuery_b(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpSpacePointQueryBlock block);
+
+typedef void (^cpSpaceSegmentQueryBlock)(cpShape *shape, cpVect point, cpVect normal, cpFloat alpha);
+void cpSpaceSegmentQuery_b(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSpaceSegmentQueryBlock block);
+
+typedef void (^cpSpaceBBQueryBlock)(cpShape *shape);
+void cpSpaceBBQuery_b(cpSpace *space, cpBB bb, cpShapeFilter filter, cpSpaceBBQueryBlock block);
+
+typedef void (^cpSpaceShapeQueryBlock)(cpShape *shape, cpContactPointSet *points);
+cpBool cpSpaceShapeQuery_b(cpSpace *space, cpShape *shape, cpSpaceShapeQueryBlock block);
+
+#endif
+#endif
+
+
+//@}
+
+#ifdef __cplusplus
+}
+
+static inline cpVect operator *(const cpVect v, const cpFloat s){return cpvmult(v, s);}
+static inline cpVect operator +(const cpVect v1, const cpVect v2){return cpvadd(v1, v2);}
+static inline cpVect operator -(const cpVect v1, const cpVect v2){return cpvsub(v1, v2);}
+static inline cpBool operator ==(const cpVect v1, const cpVect v2){return cpveql(v1, v2);}
+static inline cpVect operator -(const cpVect v){return cpvneg(v);}
+
+#endif
+#endif
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/chipmunk_ffi.h b/Chipmunk2D-7.0.2/include/chipmunk/chipmunk_ffi.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/chipmunk_ffi.h
@@ -0,0 +1,105 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifdef CHIPMUNK_FFI
+
+// Create non static inlined copies of Chipmunk functions, useful for working with dynamic FFIs
+// For many languages, it may be faster to reimplement these functions natively instead.
+// Note: This file should only be included by chipmunk.c.
+
+#ifdef _MSC_VER
+ #if _MSC_VER >= 1600
+  #define MAKE_REF(name) CP_EXPORT decltype(name) *_##name = name
+ #else
+  #define MAKE_REF(name)
+ #endif
+#else
+ #define MAKE_REF(name) __typeof__(name) *_##name = name
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+MAKE_REF(cpv); // makes a variable named _cpv that contains the function pointer for cpv()
+MAKE_REF(cpveql);
+MAKE_REF(cpvadd);
+MAKE_REF(cpvneg);
+MAKE_REF(cpvsub);
+MAKE_REF(cpvmult);
+MAKE_REF(cpvdot);
+MAKE_REF(cpvcross);
+MAKE_REF(cpvperp);
+MAKE_REF(cpvrperp);
+MAKE_REF(cpvproject);
+MAKE_REF(cpvforangle);
+MAKE_REF(cpvtoangle);
+MAKE_REF(cpvrotate);
+MAKE_REF(cpvunrotate);
+MAKE_REF(cpvlengthsq);
+MAKE_REF(cpvlength);
+MAKE_REF(cpvlerp);
+MAKE_REF(cpvnormalize);
+MAKE_REF(cpvclamp);
+MAKE_REF(cpvlerpconst);
+MAKE_REF(cpvdist);
+MAKE_REF(cpvdistsq);
+MAKE_REF(cpvnear);
+
+MAKE_REF(cpfmax);
+MAKE_REF(cpfmin);
+MAKE_REF(cpfabs);
+MAKE_REF(cpfclamp);
+MAKE_REF(cpflerp);
+MAKE_REF(cpflerpconst);
+
+MAKE_REF(cpBBNew);
+MAKE_REF(cpBBNewForExtents);
+MAKE_REF(cpBBNewForCircle);
+MAKE_REF(cpBBIntersects);
+MAKE_REF(cpBBContainsBB);
+MAKE_REF(cpBBContainsVect);
+MAKE_REF(cpBBMerge);
+MAKE_REF(cpBBExpand);
+MAKE_REF(cpBBCenter);
+MAKE_REF(cpBBArea);
+MAKE_REF(cpBBMergedArea);
+MAKE_REF(cpBBSegmentQuery);
+MAKE_REF(cpBBIntersectsSegment);
+MAKE_REF(cpBBClampVect);
+
+MAKE_REF(cpSpatialIndexDestroy);
+MAKE_REF(cpSpatialIndexCount);
+MAKE_REF(cpSpatialIndexEach);
+MAKE_REF(cpSpatialIndexContains);
+MAKE_REF(cpSpatialIndexInsert);
+MAKE_REF(cpSpatialIndexRemove);
+MAKE_REF(cpSpatialIndexReindex);
+MAKE_REF(cpSpatialIndexReindexObject);
+MAKE_REF(cpSpatialIndexSegmentQuery);
+MAKE_REF(cpSpatialIndexQuery);
+MAKE_REF(cpSpatialIndexReindexQuery);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/chipmunk_private.h b/Chipmunk2D-7.0.2/include/chipmunk/chipmunk_private.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/chipmunk_private.h
@@ -0,0 +1,344 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef CHIPMUNK_PRIVATE_H
+#define CHIPMUNK_PRIVATE_H
+
+#include "chipmunk/chipmunk.h"
+#include "chipmunk/chipmunk_structs.h"
+
+#define CP_HASH_COEF (3344921057ul)
+#define CP_HASH_PAIR(A, B) ((cpHashValue)(A)*CP_HASH_COEF ^ (cpHashValue)(B)*CP_HASH_COEF)
+
+// TODO: Eww. Magic numbers.
+#define MAGIC_EPSILON 1e-5
+
+
+//MARK: cpArray
+
+cpArray *cpArrayNew(int size);
+
+void cpArrayFree(cpArray *arr);
+
+void cpArrayPush(cpArray *arr, void *object);
+void *cpArrayPop(cpArray *arr);
+void cpArrayDeleteObj(cpArray *arr, void *obj);
+cpBool cpArrayContains(cpArray *arr, void *ptr);
+
+void cpArrayFreeEach(cpArray *arr, void (freeFunc)(void*));
+
+
+//MARK: cpHashSet
+
+typedef cpBool (*cpHashSetEqlFunc)(void *ptr, void *elt);
+typedef void *(*cpHashSetTransFunc)(void *ptr, void *data);
+
+cpHashSet *cpHashSetNew(int size, cpHashSetEqlFunc eqlFunc);
+void cpHashSetSetDefaultValue(cpHashSet *set, void *default_value);
+
+void cpHashSetFree(cpHashSet *set);
+
+int cpHashSetCount(cpHashSet *set);
+void *cpHashSetInsert(cpHashSet *set, cpHashValue hash, void *ptr, cpHashSetTransFunc trans, void *data);
+void *cpHashSetRemove(cpHashSet *set, cpHashValue hash, void *ptr);
+void *cpHashSetFind(cpHashSet *set, cpHashValue hash, void *ptr);
+
+typedef void (*cpHashSetIteratorFunc)(void *elt, void *data);
+void cpHashSetEach(cpHashSet *set, cpHashSetIteratorFunc func, void *data);
+
+typedef cpBool (*cpHashSetFilterFunc)(void *elt, void *data);
+void cpHashSetFilter(cpHashSet *set, cpHashSetFilterFunc func, void *data);
+
+
+//MARK: Bodies
+
+void cpBodyAddShape(cpBody *body, cpShape *shape);
+void cpBodyRemoveShape(cpBody *body, cpShape *shape);
+
+//void cpBodyAccumulateMassForShape(cpBody *body, cpShape *shape);
+void cpBodyAccumulateMassFromShapes(cpBody *body);
+
+void cpBodyRemoveConstraint(cpBody *body, cpConstraint *constraint);
+
+
+//MARK: Spatial Index Functions
+
+cpSpatialIndex *cpSpatialIndexInit(cpSpatialIndex *index, cpSpatialIndexClass *klass, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
+
+
+//MARK: Arbiters
+
+cpArbiter* cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b);
+
+static inline struct cpArbiterThread *
+cpArbiterThreadForBody(cpArbiter *arb, cpBody *body)
+{
+	return (arb->body_a == body ? &arb->thread_a : &arb->thread_b);
+}
+
+void cpArbiterUnthread(cpArbiter *arb);
+
+void cpArbiterUpdate(cpArbiter *arb, struct cpCollisionInfo *info, cpSpace *space);
+void cpArbiterPreStep(cpArbiter *arb, cpFloat dt, cpFloat bias, cpFloat slop);
+void cpArbiterApplyCachedImpulse(cpArbiter *arb, cpFloat dt_coef);
+void cpArbiterApplyImpulse(cpArbiter *arb);
+
+
+//MARK: Shapes/Collisions
+
+cpShape *cpShapeInit(cpShape *shape, const cpShapeClass *klass, cpBody *body, struct cpShapeMassInfo massInfo);
+
+static inline cpBool
+cpShapeActive(cpShape *shape)
+{
+	// checks if the shape is added to a shape list.
+	// TODO could this just check the space now?
+	return (shape->prev || (shape->body && shape->body->shapeList == shape));
+}
+
+// Note: This function returns contact points with r1/r2 in absolute coordinates, not body relative.
+struct cpCollisionInfo cpCollide(const cpShape *a, const cpShape *b, cpCollisionID id, struct cpContact *contacts);
+
+static inline void
+CircleSegmentQuery(cpShape *shape, cpVect center, cpFloat r1, cpVect a, cpVect b, cpFloat r2, cpSegmentQueryInfo *info)
+{
+	cpVect da = cpvsub(a, center);
+	cpVect db = cpvsub(b, center);
+	cpFloat rsum = r1 + r2;
+	
+	cpFloat qa = cpvdot(da, da) - 2.0f*cpvdot(da, db) + cpvdot(db, db);
+	cpFloat qb = cpvdot(da, db) - cpvdot(da, da);
+	cpFloat det = qb*qb - qa*(cpvdot(da, da) - rsum*rsum);
+	
+	if(det >= 0.0f){
+		cpFloat t = (-qb - cpfsqrt(det))/(qa);
+		if(0.0f<= t && t <= 1.0f){
+			cpVect n = cpvnormalize(cpvlerp(da, db, t));
+			
+			info->shape = shape;
+			info->point = cpvsub(cpvlerp(a, b, t), cpvmult(n, r2));
+			info->normal = n;
+			info->alpha = t;
+		}
+	}
+}
+
+static inline cpBool
+cpShapeFilterReject(cpShapeFilter a, cpShapeFilter b)
+{
+	// Reject the collision if:
+	return (
+		// They are in the same non-zero group.
+		(a.group != 0 && a.group == b.group) ||
+		// One of the category/mask combinations fails.
+		(a.categories & b.mask) == 0 ||
+		(b.categories & a.mask) == 0
+	);
+}
+
+void cpLoopIndexes(const cpVect *verts, int count, int *start, int *end);
+
+
+//MARK: Constraints
+// TODO naming conventions here
+
+void cpConstraintInit(cpConstraint *constraint, const struct cpConstraintClass *klass, cpBody *a, cpBody *b);
+
+static inline void
+cpConstraintActivateBodies(cpConstraint *constraint)
+{
+	cpBody *a = constraint->a; cpBodyActivate(a);
+	cpBody *b = constraint->b; cpBodyActivate(b);
+}
+
+static inline cpVect
+relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2){
+	cpVect v1_sum = cpvadd(a->v, cpvmult(cpvperp(r1), a->w));
+	cpVect v2_sum = cpvadd(b->v, cpvmult(cpvperp(r2), b->w));
+	
+	return cpvsub(v2_sum, v1_sum);
+}
+
+static inline cpFloat
+normal_relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n){
+	return cpvdot(relative_velocity(a, b, r1, r2), n);
+}
+
+static inline void
+apply_impulse(cpBody *body, cpVect j, cpVect r){
+	body->v = cpvadd(body->v, cpvmult(j, body->m_inv));
+	body->w += body->i_inv*cpvcross(r, j);
+}
+
+static inline void
+apply_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j)
+{
+	apply_impulse(a, cpvneg(j), r1);
+	apply_impulse(b, j, r2);
+}
+
+static inline void
+apply_bias_impulse(cpBody *body, cpVect j, cpVect r)
+{
+	body->v_bias = cpvadd(body->v_bias, cpvmult(j, body->m_inv));
+	body->w_bias += body->i_inv*cpvcross(r, j);
+}
+
+static inline void
+apply_bias_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j)
+{
+	apply_bias_impulse(a, cpvneg(j), r1);
+	apply_bias_impulse(b, j, r2);
+}
+
+static inline cpFloat
+k_scalar_body(cpBody *body, cpVect r, cpVect n)
+{
+	cpFloat rcn = cpvcross(r, n);
+	return body->m_inv + body->i_inv*rcn*rcn;
+}
+
+static inline cpFloat
+k_scalar(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n)
+{
+	cpFloat value = k_scalar_body(a, r1, n) + k_scalar_body(b, r2, n);
+	cpAssertSoft(value != 0.0, "Unsolvable collision or constraint.");
+	
+	return value;
+}
+
+static inline cpMat2x2
+k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2)
+{
+	cpFloat m_sum = a->m_inv + b->m_inv;
+	
+	// start with Identity*m_sum
+	cpFloat k11 = m_sum, k12 = 0.0f;
+	cpFloat k21 = 0.0f,  k22 = m_sum;
+	
+	// add the influence from r1
+	cpFloat a_i_inv = a->i_inv;
+	cpFloat r1xsq =  r1.x * r1.x * a_i_inv;
+	cpFloat r1ysq =  r1.y * r1.y * a_i_inv;
+	cpFloat r1nxy = -r1.x * r1.y * a_i_inv;
+	k11 += r1ysq; k12 += r1nxy;
+	k21 += r1nxy; k22 += r1xsq;
+	
+	// add the influnce from r2
+	cpFloat b_i_inv = b->i_inv;
+	cpFloat r2xsq =  r2.x * r2.x * b_i_inv;
+	cpFloat r2ysq =  r2.y * r2.y * b_i_inv;
+	cpFloat r2nxy = -r2.x * r2.y * b_i_inv;
+	k11 += r2ysq; k12 += r2nxy;
+	k21 += r2nxy; k22 += r2xsq;
+	
+	// invert
+	cpFloat det = k11*k22 - k12*k21;
+	cpAssertSoft(det != 0.0, "Unsolvable constraint.");
+	
+	cpFloat det_inv = 1.0f/det;
+	return cpMat2x2New(
+		 k22*det_inv, -k12*det_inv,
+		-k21*det_inv,  k11*det_inv
+ 	);
+}
+
+static inline cpFloat
+bias_coef(cpFloat errorBias, cpFloat dt)
+{
+	return 1.0f - cpfpow(errorBias, dt);
+}
+
+
+//MARK: Spaces
+
+#define cpAssertSpaceUnlocked(space) \
+	cpAssertHard(!space->locked, \
+		"This operation cannot be done safely during a call to cpSpaceStep() or during a query. " \
+		"Put these calls into a post-step callback." \
+	);
+
+void cpSpaceSetStaticBody(cpSpace *space, cpBody *body);
+
+extern cpCollisionHandler cpCollisionHandlerDoNothing;
+
+void cpSpaceProcessComponents(cpSpace *space, cpFloat dt);
+
+void cpSpacePushFreshContactBuffer(cpSpace *space);
+struct cpContact *cpContactBufferGetArray(cpSpace *space);
+void cpSpacePushContacts(cpSpace *space, int count);
+
+cpPostStepCallback *cpSpaceGetPostStepCallback(cpSpace *space, void *key);
+
+cpBool cpSpaceArbiterSetFilter(cpArbiter *arb, cpSpace *space);
+void cpSpaceFilterArbiters(cpSpace *space, cpBody *body, cpShape *filter);
+
+void cpSpaceActivateBody(cpSpace *space, cpBody *body);
+void cpSpaceLock(cpSpace *space);
+void cpSpaceUnlock(cpSpace *space, cpBool runPostStep);
+
+static inline void
+cpSpaceUncacheArbiter(cpSpace *space, cpArbiter *arb)
+{
+	const cpShape *a = arb->a, *b = arb->b;
+	const cpShape *shape_pair[] = {a, b};
+	cpHashValue arbHashID = CP_HASH_PAIR((cpHashValue)a, (cpHashValue)b);
+	cpHashSetRemove(space->cachedArbiters, arbHashID, shape_pair);
+	cpArrayDeleteObj(space->arbiters, arb);
+}
+
+static inline cpArray *
+cpSpaceArrayForBodyType(cpSpace *space, cpBodyType type)
+{
+	return (type == CP_BODY_TYPE_STATIC ? space->staticBodies : space->dynamicBodies);
+}
+
+void cpShapeUpdateFunc(cpShape *shape, void *unused);
+cpCollisionID cpSpaceCollideShapes(cpShape *a, cpShape *b, cpCollisionID id, cpSpace *space);
+
+
+//MARK: Foreach loops
+
+static inline cpConstraint *
+cpConstraintNext(cpConstraint *node, cpBody *body)
+{
+	return (node->a == body ? node->next_a : node->next_b);
+}
+
+#define CP_BODY_FOREACH_CONSTRAINT(bdy, var)\
+	for(cpConstraint *var = bdy->constraintList; var; var = cpConstraintNext(var, bdy))
+
+static inline cpArbiter *
+cpArbiterNext(cpArbiter *node, cpBody *body)
+{
+	return (node->body_a == body ? node->thread_a.next : node->thread_b.next);
+}
+
+#define CP_BODY_FOREACH_ARBITER(bdy, var)\
+	for(cpArbiter *var = bdy->arbiterList; var; var = cpArbiterNext(var, bdy))
+
+#define CP_BODY_FOREACH_SHAPE(body, var)\
+	for(cpShape *var = body->shapeList; var; var = var->next)
+
+#define CP_BODY_FOREACH_COMPONENT(root, var)\
+	for(cpBody *var = root; var; var = var->sleeping.next)
+
+#endif
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/chipmunk_structs.h b/Chipmunk2D-7.0.2/include/chipmunk/chipmunk_structs.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/chipmunk_structs.h
@@ -0,0 +1,450 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+// All of the struct definitions for Chipmunk should be considered part of the private API.
+// However, it is very valuable to know the struct sizes for preallocating memory.
+
+#ifndef CHIPMUNK_STRUCTS_H
+#define CHIPMUNK_STRUCTS_H
+
+#include "chipmunk/chipmunk.h"
+
+struct cpArray {
+	int num, max;
+	void **arr;
+};
+
+struct cpBody {
+	// Integration functions
+	cpBodyVelocityFunc velocity_func;
+	cpBodyPositionFunc position_func;
+	
+	// mass and it's inverse
+	cpFloat m;
+	cpFloat m_inv;
+	
+	// moment of inertia and it's inverse
+	cpFloat i;
+	cpFloat i_inv;
+	
+	// center of gravity
+	cpVect cog;
+	
+	// position, velocity, force
+	cpVect p;
+	cpVect v;
+	cpVect f;
+	
+	// Angle, angular velocity, torque (radians)
+	cpFloat a;
+	cpFloat w;
+	cpFloat t;
+	
+	cpTransform transform;
+	
+	cpDataPointer userData;
+	
+	// "pseudo-velocities" used for eliminating overlap.
+	// Erin Catto has some papers that talk about what these are.
+	cpVect v_bias;
+	cpFloat w_bias;
+	
+	cpSpace *space;
+	
+	cpShape *shapeList;
+	cpArbiter *arbiterList;
+	cpConstraint *constraintList;
+	
+	struct {
+		cpBody *root;
+		cpBody *next;
+		cpFloat idleTime;
+	} sleeping;
+};
+
+enum cpArbiterState {
+	// Arbiter is active and its the first collision.
+	CP_ARBITER_STATE_FIRST_COLLISION,
+	// Arbiter is active and its not the first collision.
+	CP_ARBITER_STATE_NORMAL,
+	// Collision has been explicitly ignored.
+	// Either by returning false from a begin collision handler or calling cpArbiterIgnore().
+	CP_ARBITER_STATE_IGNORE,
+	// Collison is no longer active. A space will cache an arbiter for up to cpSpace.collisionPersistence more steps.
+	CP_ARBITER_STATE_CACHED,
+	// Collison arbiter is invalid because one of the shapes was removed.
+	CP_ARBITER_STATE_INVALIDATED,
+};
+
+struct cpArbiterThread {
+	struct cpArbiter *next, *prev;
+};
+
+struct cpContact {
+	cpVect r1, r2;
+	
+	cpFloat nMass, tMass;
+	cpFloat bounce; // TODO: look for an alternate bounce solution.
+
+	cpFloat jnAcc, jtAcc, jBias;
+	cpFloat bias;
+	
+	cpHashValue hash;
+};
+
+struct cpCollisionInfo {
+	const cpShape *a, *b;
+	cpCollisionID id;
+	
+	cpVect n;
+	
+	int count;
+	// TODO Should this be a unique struct type?
+	struct cpContact *arr;
+};
+
+struct cpArbiter {
+	cpFloat e;
+	cpFloat u;
+	cpVect surface_vr;
+	
+	cpDataPointer data;
+	
+	const cpShape *a, *b;
+	cpBody *body_a, *body_b;
+	struct cpArbiterThread thread_a, thread_b;
+	
+	int count;
+	struct cpContact *contacts;
+	cpVect n;
+	
+	// Regular, wildcard A and wildcard B collision handlers.
+	cpCollisionHandler *handler, *handlerA, *handlerB;
+	cpBool swapped;
+	
+	cpTimestamp stamp;
+	enum cpArbiterState state;
+};
+
+struct cpShapeMassInfo {
+	cpFloat m;
+	cpFloat i;
+	cpVect cog;
+	cpFloat area;
+};
+
+typedef enum cpShapeType{
+	CP_CIRCLE_SHAPE,
+	CP_SEGMENT_SHAPE,
+	CP_POLY_SHAPE,
+	CP_NUM_SHAPES
+} cpShapeType;
+
+typedef cpBB (*cpShapeCacheDataImpl)(cpShape *shape, cpTransform transform);
+typedef void (*cpShapeDestroyImpl)(cpShape *shape);
+typedef void (*cpShapePointQueryImpl)(const cpShape *shape, cpVect p, cpPointQueryInfo *info);
+typedef void (*cpShapeSegmentQueryImpl)(const cpShape *shape, cpVect a, cpVect b, cpFloat radius, cpSegmentQueryInfo *info);
+
+typedef struct cpShapeClass cpShapeClass;
+
+struct cpShapeClass {
+	cpShapeType type;
+	
+	cpShapeCacheDataImpl cacheData;
+	cpShapeDestroyImpl destroy;
+	cpShapePointQueryImpl pointQuery;
+	cpShapeSegmentQueryImpl segmentQuery;
+};
+
+struct cpShape {
+	const cpShapeClass *klass;
+	
+	cpSpace *space;
+	cpBody *body;
+	struct cpShapeMassInfo massInfo;
+	cpBB bb;
+	
+	cpBool sensor;
+	
+	cpFloat e;
+	cpFloat u;
+	cpVect surfaceV;
+
+	cpDataPointer userData;
+	
+	cpCollisionType type;
+	cpShapeFilter filter;
+	
+	cpShape *next;
+	cpShape *prev;
+	
+	cpHashValue hashid;
+};
+
+struct cpCircleShape {
+	cpShape shape;
+	
+	cpVect c, tc;
+	cpFloat r;
+};
+
+struct cpSegmentShape {
+	cpShape shape;
+	
+	cpVect a, b, n;
+	cpVect ta, tb, tn;
+	cpFloat r;
+	
+	cpVect a_tangent, b_tangent;
+};
+
+struct cpSplittingPlane {
+	cpVect v0, n;
+};
+
+#define CP_POLY_SHAPE_INLINE_ALLOC 6
+
+struct cpPolyShape {
+	cpShape shape;
+	
+	cpFloat r;
+	
+	int count;
+	// The untransformed planes are appended at the end of the transformed planes.
+	struct cpSplittingPlane *planes;
+	
+	// Allocate a small number of splitting planes internally for simple poly.
+	struct cpSplittingPlane _planes[2*CP_POLY_SHAPE_INLINE_ALLOC];
+};
+
+typedef void (*cpConstraintPreStepImpl)(cpConstraint *constraint, cpFloat dt);
+typedef void (*cpConstraintApplyCachedImpulseImpl)(cpConstraint *constraint, cpFloat dt_coef);
+typedef void (*cpConstraintApplyImpulseImpl)(cpConstraint *constraint, cpFloat dt);
+typedef cpFloat (*cpConstraintGetImpulseImpl)(cpConstraint *constraint);
+
+typedef struct cpConstraintClass {
+	cpConstraintPreStepImpl preStep;
+	cpConstraintApplyCachedImpulseImpl applyCachedImpulse;
+	cpConstraintApplyImpulseImpl applyImpulse;
+	cpConstraintGetImpulseImpl getImpulse;
+} cpConstraintClass;
+
+struct cpConstraint {
+	const cpConstraintClass *klass;
+	
+	cpSpace *space;
+	
+	cpBody *a, *b;
+	cpConstraint *next_a, *next_b;
+	
+	cpFloat maxForce;
+	cpFloat errorBias;
+	cpFloat maxBias;
+	
+	cpBool collideBodies;
+	
+	cpConstraintPreSolveFunc preSolve;
+	cpConstraintPostSolveFunc postSolve;
+	
+	cpDataPointer userData;
+};
+
+struct cpPinJoint {
+	cpConstraint constraint;
+	cpVect anchorA, anchorB;
+	cpFloat dist;
+	
+	cpVect r1, r2;
+	cpVect n;
+	cpFloat nMass;
+	
+	cpFloat jnAcc;
+	cpFloat bias;
+};
+
+struct cpSlideJoint {
+	cpConstraint constraint;
+	cpVect anchorA, anchorB;
+	cpFloat min, max;
+	
+	cpVect r1, r2;
+	cpVect n;
+	cpFloat nMass;
+	
+	cpFloat jnAcc;
+	cpFloat bias;
+};
+
+struct cpPivotJoint {
+	cpConstraint constraint;
+	cpVect anchorA, anchorB;
+	
+	cpVect r1, r2;
+	cpMat2x2 k;
+	
+	cpVect jAcc;
+	cpVect bias;
+};
+
+struct cpGrooveJoint {
+	cpConstraint constraint;
+	cpVect grv_n, grv_a, grv_b;
+	cpVect  anchorB;
+	
+	cpVect grv_tn;
+	cpFloat clamp;
+	cpVect r1, r2;
+	cpMat2x2 k;
+	
+	cpVect jAcc;
+	cpVect bias;
+};
+
+struct cpDampedSpring {
+	cpConstraint constraint;
+	cpVect anchorA, anchorB;
+	cpFloat restLength;
+	cpFloat stiffness;
+	cpFloat damping;
+	cpDampedSpringForceFunc springForceFunc;
+	
+	cpFloat target_vrn;
+	cpFloat v_coef;
+	
+	cpVect r1, r2;
+	cpFloat nMass;
+	cpVect n;
+	
+	cpFloat jAcc;
+};
+
+struct cpDampedRotarySpring {
+	cpConstraint constraint;
+	cpFloat restAngle;
+	cpFloat stiffness;
+	cpFloat damping;
+	cpDampedRotarySpringTorqueFunc springTorqueFunc;
+	
+	cpFloat target_wrn;
+	cpFloat w_coef;
+	
+	cpFloat iSum;
+	cpFloat jAcc;
+};
+
+struct cpRotaryLimitJoint {
+	cpConstraint constraint;
+	cpFloat min, max;
+	
+	cpFloat iSum;
+		
+	cpFloat bias;
+	cpFloat jAcc;
+};
+
+struct cpRatchetJoint {
+	cpConstraint constraint;
+	cpFloat angle, phase, ratchet;
+	
+	cpFloat iSum;
+		
+	cpFloat bias;
+	cpFloat jAcc;
+};
+
+struct cpGearJoint {
+	cpConstraint constraint;
+	cpFloat phase, ratio;
+	cpFloat ratio_inv;
+	
+	cpFloat iSum;
+		
+	cpFloat bias;
+	cpFloat jAcc;
+};
+
+struct cpSimpleMotor {
+	cpConstraint constraint;
+	cpFloat rate;
+	
+	cpFloat iSum;
+		
+	cpFloat jAcc;
+};
+
+typedef struct cpContactBufferHeader cpContactBufferHeader;
+typedef void (*cpSpaceArbiterApplyImpulseFunc)(cpArbiter *arb);
+
+struct cpSpace {
+	int iterations;
+	
+	cpVect gravity;
+	cpFloat damping;
+	
+	cpFloat idleSpeedThreshold;
+	cpFloat sleepTimeThreshold;
+	
+	cpFloat collisionSlop;
+	cpFloat collisionBias;
+	cpTimestamp collisionPersistence;
+	
+	cpDataPointer userData;
+	
+	cpTimestamp stamp;
+	cpFloat curr_dt;
+
+	cpArray *dynamicBodies;
+	cpArray *staticBodies;
+	cpArray *rousedBodies;
+	cpArray *sleepingComponents;
+	
+	cpHashValue shapeIDCounter;
+	cpSpatialIndex *staticShapes;
+	cpSpatialIndex *dynamicShapes;
+	
+	cpArray *constraints;
+	
+	cpArray *arbiters;
+	cpContactBufferHeader *contactBuffersHead;
+	cpHashSet *cachedArbiters;
+	cpArray *pooledArbiters;
+	
+	cpArray *allocatedBuffers;
+	unsigned int locked;
+	
+	cpBool usesWildcards;
+	cpHashSet *collisionHandlers;
+	cpCollisionHandler defaultHandler;
+	
+	cpBool skipPostStep;
+	cpArray *postStepCallbacks;
+	
+	cpBody *staticBody;
+	cpBody _staticBody;
+};
+
+typedef struct cpPostStepCallback {
+	cpPostStepFunc func;
+	void *key;
+	void *data;
+} cpPostStepCallback;
+
+#endif
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/chipmunk_types.h b/Chipmunk2D-7.0.2/include/chipmunk/chipmunk_types.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/chipmunk_types.h
@@ -0,0 +1,268 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef CHIPMUNK_TYPES_H
+#define CHIPMUNK_TYPES_H
+
+#include <stdint.h>
+#include <float.h>
+#include <math.h>
+
+#ifdef __APPLE__
+   #include "TargetConditionals.h"
+#endif
+
+// Use CGTypes by default on iOS and Mac.
+// Also enables usage of doubles on 64 bit.
+// Performance is usually very comparable when the CPU cache is well utilised.
+#if (TARGET_OS_IPHONE || TARGET_OS_MAC) && (!defined CP_USE_CGTYPES)
+	#define CP_USE_CGTYPES 1
+#endif
+
+#if CP_USE_CGTYPES
+	#if TARGET_OS_IPHONE
+		#include <CoreGraphics/CGGeometry.h>
+		#include <CoreGraphics/CGAffineTransform.h>
+	#elif TARGET_OS_MAC
+		#include <ApplicationServices/ApplicationServices.h>
+	#endif
+	
+	#if defined(__LP64__) && __LP64__
+		#define CP_USE_DOUBLES 1
+	#else
+		#define CP_USE_DOUBLES 0
+	#endif
+#endif
+
+#ifndef CP_USE_DOUBLES
+	// Use doubles by default for higher precision.
+	#define CP_USE_DOUBLES 1
+#endif
+
+/// @defgroup basicTypes Basic Types
+/// Most of these types can be configured at compile time.
+/// @{
+
+#if CP_USE_DOUBLES
+/// Chipmunk's floating point type.
+/// Can be reconfigured at compile time.
+	typedef double cpFloat;
+	#define cpfsqrt sqrt
+	#define cpfsin sin
+	#define cpfcos cos
+	#define cpfacos acos
+	#define cpfatan2 atan2
+	#define cpfmod fmod
+	#define cpfexp exp
+	#define cpfpow pow
+	#define cpffloor floor
+	#define cpfceil ceil
+	#define CPFLOAT_MIN DBL_MIN
+#else
+	typedef float cpFloat;
+	#define cpfsqrt sqrtf
+	#define cpfsin sinf
+	#define cpfcos cosf
+	#define cpfacos acosf
+	#define cpfatan2 atan2f
+	#define cpfmod fmodf
+	#define cpfexp expf
+	#define cpfpow powf
+	#define cpffloor floorf
+	#define cpfceil ceilf
+	#define CPFLOAT_MIN FLT_MIN
+#endif
+
+#ifndef INFINITY
+	#ifdef _MSC_VER
+		union MSVC_EVIL_FLOAT_HACK
+		{
+			unsigned __int8 Bytes[4];
+			float Value;
+		};
+		static union MSVC_EVIL_FLOAT_HACK INFINITY_HACK = {{0x00, 0x00, 0x80, 0x7F}};
+		#define INFINITY (INFINITY_HACK.Value)
+	#endif
+	
+	#ifdef __GNUC__
+		#define INFINITY (__builtin_inf())
+	#endif
+	
+	#ifndef INFINITY
+		#define INFINITY (1e1000)
+	#endif
+#endif
+
+
+#define CP_PI ((cpFloat)3.14159265358979323846264338327950288)
+
+
+/// Return the max of two cpFloats.
+static inline cpFloat cpfmax(cpFloat a, cpFloat b)
+{
+	return (a > b) ? a : b;
+}
+
+/// Return the min of two cpFloats.
+static inline cpFloat cpfmin(cpFloat a, cpFloat b)
+{
+	return (a < b) ? a : b;
+}
+
+/// Return the absolute value of a cpFloat.
+static inline cpFloat cpfabs(cpFloat f)
+{
+	return (f < 0) ? -f : f;
+}
+
+/// Clamp @c f to be between @c min and @c max.
+static inline cpFloat cpfclamp(cpFloat f, cpFloat min, cpFloat max)
+{
+	return cpfmin(cpfmax(f, min), max);
+}
+
+/// Clamp @c f to be between 0 and 1.
+static inline cpFloat cpfclamp01(cpFloat f)
+{
+	return cpfmax(0.0f, cpfmin(f, 1.0f));
+}
+
+
+
+/// Linearly interpolate (or extrapolate) between @c f1 and @c f2 by @c t percent.
+static inline cpFloat cpflerp(cpFloat f1, cpFloat f2, cpFloat t)
+{
+	return f1*(1.0f - t) + f2*t;
+}
+
+/// Linearly interpolate from @c f1 to @c f2 by no more than @c d.
+static inline cpFloat cpflerpconst(cpFloat f1, cpFloat f2, cpFloat d)
+{
+	return f1 + cpfclamp(f2 - f1, -d, d);
+}
+
+/// Hash value type.
+#ifdef CP_HASH_VALUE_TYPE
+	typedef CP_HASH_VALUE_TYPE cpHashValue;
+#else
+	typedef uintptr_t cpHashValue;
+#endif
+
+/// Type used internally to cache colliding object info for cpCollideShapes().
+/// Should be at least 32 bits.
+typedef uint32_t cpCollisionID;
+
+// Oh C, how we love to define our own boolean types to get compiler compatibility
+/// Chipmunk's boolean type.
+#ifdef CP_BOOL_TYPE
+	typedef CP_BOOL_TYPE cpBool;
+#else
+	typedef unsigned char cpBool;
+#endif
+
+#ifndef cpTrue
+/// true value.
+	#define cpTrue 1
+#endif
+
+#ifndef cpFalse
+/// false value.
+	#define cpFalse 0
+#endif
+
+#ifdef CP_DATA_POINTER_TYPE
+	typedef CP_DATA_POINTER_TYPE cpDataPointer;
+#else
+/// Type used for user data pointers.
+	typedef void * cpDataPointer;
+#endif
+
+#ifdef CP_COLLISION_TYPE_TYPE
+	typedef CP_COLLISION_TYPE_TYPE cpCollisionType;
+#else
+/// Type used for cpSpace.collision_type.
+	typedef uintptr_t cpCollisionType;
+#endif
+
+#ifdef CP_GROUP_TYPE
+	typedef CP_GROUP_TYPE cpGroup;
+#else
+/// Type used for cpShape.group.
+	typedef uintptr_t cpGroup;
+#endif
+
+#ifdef CP_BITMASK_TYPE
+	typedef CP_BITMASK_TYPE cpBitmask;
+#else
+/// Type used for cpShapeFilter category and mask.
+	typedef unsigned int cpBitmask;
+#endif
+
+#ifdef CP_TIMESTAMP_TYPE
+	typedef CP_TIMESTAMP_TYPE cpTimestamp;
+#else
+/// Type used for various timestamps in Chipmunk.
+	typedef unsigned int cpTimestamp;
+#endif
+
+#ifndef CP_NO_GROUP
+/// Value for cpShape.group signifying that a shape is in no group.
+	#define CP_NO_GROUP ((cpGroup)0)
+#endif
+
+#ifndef CP_ALL_CATEGORIES
+/// Value for cpShape.layers signifying that a shape is in every layer.
+	#define CP_ALL_CATEGORIES (~(cpBitmask)0)
+#endif
+
+#ifndef CP_WILDCARD_COLLISION_TYPE
+/// cpCollisionType value internally reserved for hashing wildcard handlers.
+	#define CP_WILDCARD_COLLISION_TYPE (~(cpCollisionType)0)
+#endif
+
+/// @}
+
+// CGPoints are structurally the same, and allow
+// easy interoperability with other Cocoa libraries
+#if CP_USE_CGTYPES
+	typedef CGPoint cpVect;
+#else
+/// Chipmunk's 2D vector type.
+/// @addtogroup cpVect
+	typedef struct cpVect{cpFloat x,y;} cpVect;
+#endif
+
+#if CP_USE_CGTYPES
+	typedef CGAffineTransform cpTransform;
+#else
+	/// Column major affine transform.
+	typedef struct cpTransform {
+		cpFloat a, b, c, d, tx, ty;
+	} cpTransform;
+#endif
+
+// NUKE
+typedef struct cpMat2x2 {
+	// Row major [[a, b][c d]]
+	cpFloat a, b, c, d;
+} cpMat2x2;
+
+#endif
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/chipmunk_unsafe.h b/Chipmunk2D-7.0.2/include/chipmunk/chipmunk_unsafe.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/chipmunk_unsafe.h
@@ -0,0 +1,66 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* This header defines a number of "unsafe" operations on Chipmunk objects.
+ * In this case "unsafe" is referring to operations which may reduce the
+ * physical accuracy or numerical stability of the simulation, but will not
+ * cause crashes.
+ *
+ * The prime example is mutating collision shapes. Chipmunk does not support
+ * this directly. Mutating shapes using this API will caused objects in contact
+ * to be pushed apart using Chipmunk's overlap solver, but not using real
+ * persistent velocities. Probably not what you meant, but perhaps close enough.
+ */
+
+/// @defgroup unsafe Chipmunk Unsafe Shape Operations
+/// These functions are used for mutating collision shapes.
+/// Chipmunk does not have any way to get velocity information on changing shapes,
+/// so the results will be unrealistic. You must explicity include the chipmunk_unsafe.h header to use them.
+/// @{
+
+#ifndef CHIPMUNK_UNSAFE_H
+#define CHIPMUNK_UNSAFE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Set the radius of a circle shape.
+CP_EXPORT void cpCircleShapeSetRadius(cpShape *shape, cpFloat radius);
+/// Set the offset of a circle shape.
+CP_EXPORT void cpCircleShapeSetOffset(cpShape *shape, cpVect offset);
+
+/// Set the endpoints of a segment shape.
+CP_EXPORT void cpSegmentShapeSetEndpoints(cpShape *shape, cpVect a, cpVect b);
+/// Set the radius of a segment shape.
+CP_EXPORT void cpSegmentShapeSetRadius(cpShape *shape, cpFloat radius);
+
+/// Set the vertexes of a poly shape.
+CP_EXPORT void cpPolyShapeSetVerts(cpShape *shape, int count, cpVect *verts, cpTransform transform);
+CP_EXPORT void cpPolyShapeSetVertsRaw(cpShape *shape, int count, cpVect *verts);
+/// Set the radius of a poly shape.
+CP_EXPORT void cpPolyShapeSetRadius(cpShape *shape, cpFloat radius);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/// @}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpArbiter.h b/Chipmunk2D-7.0.2/include/chipmunk/cpArbiter.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpArbiter.h
@@ -0,0 +1,145 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpArbiter cpArbiter
+/// The cpArbiter struct tracks pairs of colliding shapes.
+/// They are also used in conjuction with collision handler callbacks
+/// allowing you to retrieve information on the collision or change it.
+/// A unique arbiter value is used for each pair of colliding objects. It persists until the shapes separate.
+/// @{
+
+#define CP_MAX_CONTACTS_PER_ARBITER 2
+
+/// Get the restitution (elasticity) that will be applied to the pair of colliding objects.
+CP_EXPORT cpFloat cpArbiterGetRestitution(const cpArbiter *arb);
+/// Override the restitution (elasticity) that will be applied to the pair of colliding objects.
+CP_EXPORT void cpArbiterSetRestitution(cpArbiter *arb, cpFloat restitution);
+/// Get the friction coefficient that will be applied to the pair of colliding objects.
+CP_EXPORT cpFloat cpArbiterGetFriction(const cpArbiter *arb);
+/// Override the friction coefficient that will be applied to the pair of colliding objects.
+CP_EXPORT void cpArbiterSetFriction(cpArbiter *arb, cpFloat friction);
+
+// Get the relative surface velocity of the two shapes in contact.
+CP_EXPORT cpVect cpArbiterGetSurfaceVelocity(cpArbiter *arb);
+
+// Override the relative surface velocity of the two shapes in contact.
+// By default this is calculated to be the difference of the two surface velocities clamped to the tangent plane.
+CP_EXPORT void cpArbiterSetSurfaceVelocity(cpArbiter *arb, cpVect vr);
+
+/// Get the user data pointer associated with this pair of colliding objects.
+CP_EXPORT cpDataPointer cpArbiterGetUserData(const cpArbiter *arb);
+/// Set a user data point associated with this pair of colliding objects.
+/// If you need to perform any cleanup for this pointer, you must do it yourself, in the separate callback for instance.
+CP_EXPORT void cpArbiterSetUserData(cpArbiter *arb, cpDataPointer userData);
+
+/// Calculate the total impulse including the friction that was applied by this arbiter.
+/// This function should only be called from a post-solve, post-step or cpBodyEachArbiter callback.
+CP_EXPORT cpVect cpArbiterTotalImpulse(const cpArbiter *arb);
+/// Calculate the amount of energy lost in a collision including static, but not dynamic friction.
+/// This function should only be called from a post-solve, post-step or cpBodyEachArbiter callback.
+CP_EXPORT cpFloat cpArbiterTotalKE(const cpArbiter *arb);
+
+/// Mark a collision pair to be ignored until the two objects separate.
+/// Pre-solve and post-solve callbacks will not be called, but the separate callback will be called.
+CP_EXPORT cpBool cpArbiterIgnore(cpArbiter *arb);
+
+/// Return the colliding shapes involved for this arbiter.
+/// The order of their cpSpace.collision_type values will match
+/// the order set when the collision handler was registered.
+CP_EXPORT void cpArbiterGetShapes(const cpArbiter *arb, cpShape **a, cpShape **b);
+
+/// A macro shortcut for defining and retrieving the shapes from an arbiter.
+#define CP_ARBITER_GET_SHAPES(__arb__, __a__, __b__) cpShape *__a__, *__b__; cpArbiterGetShapes(__arb__, &__a__, &__b__);
+
+/// Return the colliding bodies involved for this arbiter.
+/// The order of the cpSpace.collision_type the bodies are associated with values will match
+/// the order set when the collision handler was registered.
+CP_EXPORT void cpArbiterGetBodies(const cpArbiter *arb, cpBody **a, cpBody **b);
+
+/// A macro shortcut for defining and retrieving the bodies from an arbiter.
+#define CP_ARBITER_GET_BODIES(__arb__, __a__, __b__) cpBody *__a__, *__b__; cpArbiterGetBodies(__arb__, &__a__, &__b__);
+
+/// A struct that wraps up the important collision data for an arbiter.
+struct cpContactPointSet {
+	/// The number of contact points in the set.
+	int count;
+	
+	/// The normal of the collision.
+	cpVect normal;
+	
+	/// The array of contact points.
+	struct {
+		/// The position of the contact on the surface of each shape.
+		cpVect pointA, pointB;
+		/// Penetration distance of the two shapes. Overlapping means it will be negative.
+		/// This value is calculated as cpvdot(cpvsub(point2, point1), normal) and is ignored by cpArbiterSetContactPointSet().
+		cpFloat distance;
+	} points[CP_MAX_CONTACTS_PER_ARBITER];
+};
+
+/// Return a contact set from an arbiter.
+CP_EXPORT cpContactPointSet cpArbiterGetContactPointSet(const cpArbiter *arb);
+
+/// Replace the contact point set for an arbiter.
+/// This can be a very powerful feature, but use it with caution!
+CP_EXPORT void cpArbiterSetContactPointSet(cpArbiter *arb, cpContactPointSet *set);
+
+/// Returns true if this is the first step a pair of objects started colliding.
+CP_EXPORT cpBool cpArbiterIsFirstContact(const cpArbiter *arb);
+/// Returns true if the separate callback is due to a shape being removed from the space.
+CP_EXPORT cpBool cpArbiterIsRemoval(const cpArbiter *arb);
+
+/// Get the number of contact points for this arbiter.
+CP_EXPORT int cpArbiterGetCount(const cpArbiter *arb);
+/// Get the normal of the collision.
+CP_EXPORT cpVect cpArbiterGetNormal(const cpArbiter *arb);
+/// Get the position of the @c ith contact point on the surface of the first shape.
+CP_EXPORT cpVect cpArbiterGetPointA(const cpArbiter *arb, int i);
+/// Get the position of the @c ith contact point on the surface of the second shape.
+CP_EXPORT cpVect cpArbiterGetPointB(const cpArbiter *arb, int i);
+/// Get the depth of the @c ith contact point.
+CP_EXPORT cpFloat cpArbiterGetDepth(const cpArbiter *arb, int i);
+
+/// If you want a custom callback to invoke the wildcard callback for the first collision type, you must call this function explicitly.
+/// You must decide how to handle the wildcard's return value since it may disagree with the other wildcard handler's return value or your own.
+CP_EXPORT cpBool cpArbiterCallWildcardBeginA(cpArbiter *arb, cpSpace *space);
+/// If you want a custom callback to invoke the wildcard callback for the second collision type, you must call this function explicitly.
+/// You must decide how to handle the wildcard's return value since it may disagree with the other wildcard handler's return value or your own.
+CP_EXPORT cpBool cpArbiterCallWildcardBeginB(cpArbiter *arb, cpSpace *space);
+
+/// If you want a custom callback to invoke the wildcard callback for the first collision type, you must call this function explicitly.
+/// You must decide how to handle the wildcard's return value since it may disagree with the other wildcard handler's return value or your own.
+CP_EXPORT cpBool cpArbiterCallWildcardPreSolveA(cpArbiter *arb, cpSpace *space);
+/// If you want a custom callback to invoke the wildcard callback for the second collision type, you must call this function explicitly.
+/// You must decide how to handle the wildcard's return value since it may disagree with the other wildcard handler's return value or your own.
+CP_EXPORT cpBool cpArbiterCallWildcardPreSolveB(cpArbiter *arb, cpSpace *space);
+
+/// If you want a custom callback to invoke the wildcard callback for the first collision type, you must call this function explicitly.
+CP_EXPORT void cpArbiterCallWildcardPostSolveA(cpArbiter *arb, cpSpace *space);
+/// If you want a custom callback to invoke the wildcard callback for the second collision type, you must call this function explicitly.
+CP_EXPORT void cpArbiterCallWildcardPostSolveB(cpArbiter *arb, cpSpace *space);
+
+/// If you want a custom callback to invoke the wildcard callback for the first collision type, you must call this function explicitly.
+CP_EXPORT void cpArbiterCallWildcardSeparateA(cpArbiter *arb, cpSpace *space);
+/// If you want a custom callback to invoke the wildcard callback for the second collision type, you must call this function explicitly.
+CP_EXPORT void cpArbiterCallWildcardSeparateB(cpArbiter *arb, cpSpace *space);
+
+/// @}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpBB.h b/Chipmunk2D-7.0.2/include/chipmunk/cpBB.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpBB.h
@@ -0,0 +1,187 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef CHIPMUNK_BB_H
+#define CHIPMUNK_BB_H
+
+#include "chipmunk_types.h"
+#include "cpVect.h"
+
+/// @defgroup cpBBB cpBB
+/// Chipmunk's axis-aligned 2D bounding box type along with a few handy routines.
+/// @{
+
+/// Chipmunk's axis-aligned 2D bounding box type. (left, bottom, right, top)
+typedef struct cpBB{
+	cpFloat l, b, r ,t;
+} cpBB;
+
+/// Convenience constructor for cpBB structs.
+static inline cpBB cpBBNew(const cpFloat l, const cpFloat b, const cpFloat r, const cpFloat t)
+{
+	cpBB bb = {l, b, r, t};
+	return bb;
+}
+
+/// Constructs a cpBB centered on a point with the given extents (half sizes).
+static inline cpBB
+cpBBNewForExtents(const cpVect c, const cpFloat hw, const cpFloat hh)
+{
+	return cpBBNew(c.x - hw, c.y - hh, c.x + hw, c.y + hh);
+}
+
+/// Constructs a cpBB for a circle with the given position and radius.
+static inline cpBB cpBBNewForCircle(const cpVect p, const cpFloat r)
+{
+	return cpBBNewForExtents(p, r, r);
+}
+
+/// Returns true if @c a and @c b intersect.
+static inline cpBool cpBBIntersects(const cpBB a, const cpBB b)
+{
+	return (a.l <= b.r && b.l <= a.r && a.b <= b.t && b.b <= a.t);
+}
+
+/// Returns true if @c other lies completely within @c bb.
+static inline cpBool cpBBContainsBB(const cpBB bb, const cpBB other)
+{
+	return (bb.l <= other.l && bb.r >= other.r && bb.b <= other.b && bb.t >= other.t);
+}
+
+/// Returns true if @c bb contains @c v.
+static inline cpBool cpBBContainsVect(const cpBB bb, const cpVect v)
+{
+	return (bb.l <= v.x && bb.r >= v.x && bb.b <= v.y && bb.t >= v.y);
+}
+
+/// Returns a bounding box that holds both bounding boxes.
+static inline cpBB cpBBMerge(const cpBB a, const cpBB b){
+	return cpBBNew(
+		cpfmin(a.l, b.l),
+		cpfmin(a.b, b.b),
+		cpfmax(a.r, b.r),
+		cpfmax(a.t, b.t)
+	);
+}
+
+/// Returns a bounding box that holds both @c bb and @c v.
+static inline cpBB cpBBExpand(const cpBB bb, const cpVect v){
+	return cpBBNew(
+		cpfmin(bb.l, v.x),
+		cpfmin(bb.b, v.y),
+		cpfmax(bb.r, v.x),
+		cpfmax(bb.t, v.y)
+	);
+}
+
+/// Returns the center of a bounding box.
+static inline cpVect
+cpBBCenter(cpBB bb)
+{
+	return cpvlerp(cpv(bb.l, bb.b), cpv(bb.r, bb.t), 0.5f);
+}
+
+/// Returns the area of the bounding box.
+static inline cpFloat cpBBArea(cpBB bb)
+{
+	return (bb.r - bb.l)*(bb.t - bb.b);
+}
+
+/// Merges @c a and @c b and returns the area of the merged bounding box.
+static inline cpFloat cpBBMergedArea(cpBB a, cpBB b)
+{
+	return (cpfmax(a.r, b.r) - cpfmin(a.l, b.l))*(cpfmax(a.t, b.t) - cpfmin(a.b, b.b));
+}
+
+/// Returns the fraction along the segment query the cpBB is hit. Returns INFINITY if it doesn't hit.
+static inline cpFloat cpBBSegmentQuery(cpBB bb, cpVect a, cpVect b)
+{
+	cpVect delta = cpvsub(b, a);
+	cpFloat tmin = -INFINITY, tmax = INFINITY;
+	
+	if(delta.x == 0.0f){
+		if(a.x < bb.l || bb.r < a.x) return INFINITY;
+	} else {
+		cpFloat t1 = (bb.l - a.x)/delta.x;
+		cpFloat t2 = (bb.r - a.x)/delta.x;
+		tmin = cpfmax(tmin, cpfmin(t1, t2));
+		tmax = cpfmin(tmax, cpfmax(t1, t2));
+	}
+	
+	if(delta.y == 0.0f){
+		if(a.y < bb.b || bb.t < a.y) return INFINITY;
+	} else {
+		cpFloat t1 = (bb.b - a.y)/delta.y;
+		cpFloat t2 = (bb.t - a.y)/delta.y;
+		tmin = cpfmax(tmin, cpfmin(t1, t2));
+		tmax = cpfmin(tmax, cpfmax(t1, t2));
+	}
+	
+	if(tmin <= tmax && 0.0f <= tmax && tmin <= 1.0f){
+		return cpfmax(tmin, 0.0f);
+	} else {
+		return INFINITY;
+	}
+}
+
+/// Return true if the bounding box intersects the line segment with ends @c a and @c b.
+static inline cpBool cpBBIntersectsSegment(cpBB bb, cpVect a, cpVect b)
+{
+	return (cpBBSegmentQuery(bb, a, b) != INFINITY);
+}
+
+/// Clamp a vector to a bounding box.
+static inline cpVect
+cpBBClampVect(const cpBB bb, const cpVect v)
+{
+	return cpv(cpfclamp(v.x, bb.l, bb.r), cpfclamp(v.y, bb.b, bb.t));
+}
+
+/// Wrap a vector to a bounding box.
+static inline cpVect
+cpBBWrapVect(const cpBB bb, const cpVect v)
+{
+	cpFloat dx = cpfabs(bb.r - bb.l);
+	cpFloat modx = cpfmod(v.x - bb.l, dx);
+	cpFloat x = (modx > 0.0f) ? modx : modx + dx;
+	
+	cpFloat dy = cpfabs(bb.t - bb.b);
+	cpFloat mody = cpfmod(v.y - bb.b, dy);
+	cpFloat y = (mody > 0.0f) ? mody : mody + dy;
+	
+	return cpv(x + bb.l, y + bb.b);
+}
+
+/// Returns a bounding box offseted by @c v.
+static inline cpBB
+cpBBOffset(const cpBB bb, const cpVect v)
+{
+	return cpBBNew(
+		bb.l + v.x,
+		bb.b + v.y,
+		bb.r + v.x,
+		bb.t + v.y
+	);
+}
+
+///@}
+
+#endif
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpBody.h b/Chipmunk2D-7.0.2/include/chipmunk/cpBody.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpBody.h
@@ -0,0 +1,189 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpBody cpBody
+/// Chipmunk's rigid body type. Rigid bodies hold the physical properties of an object like
+/// it's mass, and position and velocity of it's center of gravity. They don't have an shape on their own.
+/// They are given a shape by creating collision shapes (cpShape) that point to the body.
+/// @{
+
+typedef enum cpBodyType {
+	/// A dynamic body is one that is affected by gravity, forces, and collisions.
+	/// This is the default body type.
+	CP_BODY_TYPE_DYNAMIC,
+	/// A kinematic body is an infinite mass, user controlled body that is not affected by gravity, forces or collisions.
+	/// Instead the body only moves based on it's velocity.
+	/// Dynamic bodies collide normally with kinematic bodies, though the kinematic body will be unaffected.
+	/// Collisions between two kinematic bodies, or a kinematic body and a static body produce collision callbacks, but no collision response.
+	CP_BODY_TYPE_KINEMATIC,
+	/// A static body is a body that never (or rarely) moves. If you move a static body, you must call one of the cpSpaceReindex*() functions.
+	/// Chipmunk uses this information to optimize the collision detection.
+	/// Static bodies do not produce collision callbacks when colliding with other static bodies.
+	CP_BODY_TYPE_STATIC,
+} cpBodyType;
+
+/// Rigid body velocity update function type.
+typedef void (*cpBodyVelocityFunc)(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);
+/// Rigid body position update function type.
+typedef void (*cpBodyPositionFunc)(cpBody *body, cpFloat dt);
+
+/// Allocate a cpBody.
+CP_EXPORT cpBody* cpBodyAlloc(void);
+/// Initialize a cpBody.
+CP_EXPORT cpBody* cpBodyInit(cpBody *body, cpFloat mass, cpFloat moment);
+/// Allocate and initialize a cpBody.
+CP_EXPORT cpBody* cpBodyNew(cpFloat mass, cpFloat moment);
+
+/// Allocate and initialize a cpBody, and set it as a kinematic body.
+CP_EXPORT cpBody* cpBodyNewKinematic(void);
+/// Allocate and initialize a cpBody, and set it as a static body.
+CP_EXPORT cpBody* cpBodyNewStatic(void);
+
+/// Destroy a cpBody.
+CP_EXPORT void cpBodyDestroy(cpBody *body);
+/// Destroy and free a cpBody.
+CP_EXPORT void cpBodyFree(cpBody *body);
+
+// Defined in cpSpace.c
+/// Wake up a sleeping or idle body.
+CP_EXPORT void cpBodyActivate(cpBody *body);
+/// Wake up any sleeping or idle bodies touching a static body.
+CP_EXPORT void cpBodyActivateStatic(cpBody *body, cpShape *filter);
+
+/// Force a body to fall asleep immediately.
+CP_EXPORT void cpBodySleep(cpBody *body);
+/// Force a body to fall asleep immediately along with other bodies in a group.
+CP_EXPORT void cpBodySleepWithGroup(cpBody *body, cpBody *group);
+
+/// Returns true if the body is sleeping.
+CP_EXPORT cpBool cpBodyIsSleeping(const cpBody *body);
+
+/// Get the type of the body.
+CP_EXPORT cpBodyType cpBodyGetType(cpBody *body);
+/// Set the type of the body.
+CP_EXPORT void cpBodySetType(cpBody *body, cpBodyType type);
+
+/// Get the space this body is added to.
+CP_EXPORT cpSpace* cpBodyGetSpace(const cpBody *body);
+
+/// Get the mass of the body.
+CP_EXPORT cpFloat cpBodyGetMass(const cpBody *body);
+/// Set the mass of the body.
+CP_EXPORT void cpBodySetMass(cpBody *body, cpFloat m);
+
+/// Get the moment of inertia of the body.
+CP_EXPORT cpFloat cpBodyGetMoment(const cpBody *body);
+/// Set the moment of inertia of the body.
+CP_EXPORT void cpBodySetMoment(cpBody *body, cpFloat i);
+
+/// Set the position of a body.
+CP_EXPORT cpVect cpBodyGetPosition(const cpBody *body);
+/// Set the position of the body.
+CP_EXPORT void cpBodySetPosition(cpBody *body, cpVect pos);
+
+/// Get the offset of the center of gravity in body local coordinates.
+CP_EXPORT cpVect cpBodyGetCenterOfGravity(const cpBody *body);
+/// Set the offset of the center of gravity in body local coordinates.
+CP_EXPORT void cpBodySetCenterOfGravity(cpBody *body, cpVect cog);
+
+/// Get the velocity of the body.
+CP_EXPORT cpVect cpBodyGetVelocity(const cpBody *body);
+/// Set the velocity of the body.
+CP_EXPORT void cpBodySetVelocity(cpBody *body, cpVect velocity);
+
+/// Get the force applied to the body for the next time step.
+CP_EXPORT cpVect cpBodyGetForce(const cpBody *body);
+/// Set the force applied to the body for the next time step.
+CP_EXPORT void cpBodySetForce(cpBody *body, cpVect force);
+
+/// Get the angle of the body.
+CP_EXPORT cpFloat cpBodyGetAngle(const cpBody *body);
+/// Set the angle of a body.
+CP_EXPORT void cpBodySetAngle(cpBody *body, cpFloat a);
+
+/// Get the angular velocity of the body.
+CP_EXPORT cpFloat cpBodyGetAngularVelocity(const cpBody *body);
+/// Set the angular velocity of the body.
+CP_EXPORT void cpBodySetAngularVelocity(cpBody *body, cpFloat angularVelocity);
+
+/// Get the torque applied to the body for the next time step.
+CP_EXPORT cpFloat cpBodyGetTorque(const cpBody *body);
+/// Set the torque applied to the body for the next time step.
+CP_EXPORT void cpBodySetTorque(cpBody *body, cpFloat torque);
+
+/// Get the rotation vector of the body. (The x basis vector of it's transform.)
+CP_EXPORT cpVect cpBodyGetRotation(const cpBody *body);
+
+/// Get the user data pointer assigned to the body.
+CP_EXPORT cpDataPointer cpBodyGetUserData(const cpBody *body);
+/// Set the user data pointer assigned to the body.
+CP_EXPORT void cpBodySetUserData(cpBody *body, cpDataPointer userData);
+
+/// Set the callback used to update a body's velocity.
+CP_EXPORT void cpBodySetVelocityUpdateFunc(cpBody *body, cpBodyVelocityFunc velocityFunc);
+/// Set the callback used to update a body's position.
+/// NOTE: It's not generally recommended to override this unless you call the default position update function.
+CP_EXPORT void cpBodySetPositionUpdateFunc(cpBody *body, cpBodyPositionFunc positionFunc);
+
+/// Default velocity integration function..
+CP_EXPORT void cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);
+/// Default position integration function.
+CP_EXPORT void cpBodyUpdatePosition(cpBody *body, cpFloat dt);
+
+/// Convert body relative/local coordinates to absolute/world coordinates.
+CP_EXPORT cpVect cpBodyLocalToWorld(const cpBody *body, const cpVect point);
+/// Convert body absolute/world coordinates to  relative/local coordinates.
+CP_EXPORT cpVect cpBodyWorldToLocal(const cpBody *body, const cpVect point);
+
+/// Apply a force to a body. Both the force and point are expressed in world coordinates.
+CP_EXPORT void cpBodyApplyForceAtWorldPoint(cpBody *body, cpVect force, cpVect point);
+/// Apply a force to a body. Both the force and point are expressed in body local coordinates.
+CP_EXPORT void cpBodyApplyForceAtLocalPoint(cpBody *body, cpVect force, cpVect point);
+
+/// Apply an impulse to a body. Both the impulse and point are expressed in world coordinates.
+CP_EXPORT void cpBodyApplyImpulseAtWorldPoint(cpBody *body, cpVect impulse, cpVect point);
+/// Apply an impulse to a body. Both the impulse and point are expressed in body local coordinates.
+CP_EXPORT void cpBodyApplyImpulseAtLocalPoint(cpBody *body, cpVect impulse, cpVect point);
+
+/// Get the velocity on a body (in world units) at a point on the body in world coordinates.
+CP_EXPORT cpVect cpBodyGetVelocityAtWorldPoint(const cpBody *body, cpVect point);
+/// Get the velocity on a body (in world units) at a point on the body in local coordinates.
+CP_EXPORT cpVect cpBodyGetVelocityAtLocalPoint(const cpBody *body, cpVect point);
+
+/// Get the amount of kinetic energy contained by the body.
+CP_EXPORT cpFloat cpBodyKineticEnergy(const cpBody *body);
+
+/// Body/shape iterator callback function type. 
+typedef void (*cpBodyShapeIteratorFunc)(cpBody *body, cpShape *shape, void *data);
+/// Call @c func once for each shape attached to @c body and added to the space.
+CP_EXPORT void cpBodyEachShape(cpBody *body, cpBodyShapeIteratorFunc func, void *data);
+
+/// Body/constraint iterator callback function type. 
+typedef void (*cpBodyConstraintIteratorFunc)(cpBody *body, cpConstraint *constraint, void *data);
+/// Call @c func once for each constraint attached to @c body and added to the space.
+CP_EXPORT void cpBodyEachConstraint(cpBody *body, cpBodyConstraintIteratorFunc func, void *data);
+
+/// Body/arbiter iterator callback function type. 
+typedef void (*cpBodyArbiterIteratorFunc)(cpBody *body, cpArbiter *arbiter, void *data);
+/// Call @c func once for each arbiter that is currently active on the body.
+CP_EXPORT void cpBodyEachArbiter(cpBody *body, cpBodyArbiterIteratorFunc func, void *data);
+
+///@}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpConstraint.h b/Chipmunk2D-7.0.2/include/chipmunk/cpConstraint.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpConstraint.h
@@ -0,0 +1,95 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpConstraint cpConstraint
+/// @{
+
+/// Callback function type that gets called before solving a joint.
+typedef void (*cpConstraintPreSolveFunc)(cpConstraint *constraint, cpSpace *space);
+/// Callback function type that gets called after solving a joint.
+typedef void (*cpConstraintPostSolveFunc)(cpConstraint *constraint, cpSpace *space);
+
+/// Destroy a constraint.
+CP_EXPORT void cpConstraintDestroy(cpConstraint *constraint);
+/// Destroy and free a constraint.
+CP_EXPORT void cpConstraintFree(cpConstraint *constraint);
+
+/// Get the cpSpace this constraint is added to.
+CP_EXPORT cpSpace* cpConstraintGetSpace(const cpConstraint *constraint);
+
+/// Get the first body the constraint is attached to.
+CP_EXPORT cpBody* cpConstraintGetBodyA(const cpConstraint *constraint);
+
+/// Get the second body the constraint is attached to.
+CP_EXPORT cpBody* cpConstraintGetBodyB(const cpConstraint *constraint);
+
+/// Get the maximum force that this constraint is allowed to use.
+CP_EXPORT cpFloat cpConstraintGetMaxForce(const cpConstraint *constraint);
+/// Set the maximum force that this constraint is allowed to use. (defaults to INFINITY)
+CP_EXPORT void cpConstraintSetMaxForce(cpConstraint *constraint, cpFloat maxForce);
+
+/// Get rate at which joint error is corrected.
+CP_EXPORT cpFloat cpConstraintGetErrorBias(const cpConstraint *constraint);
+/// Set rate at which joint error is corrected.
+/// Defaults to pow(1.0 - 0.1, 60.0) meaning that it will
+/// correct 10% of the error every 1/60th of a second.
+CP_EXPORT void cpConstraintSetErrorBias(cpConstraint *constraint, cpFloat errorBias);
+
+/// Get the maximum rate at which joint error is corrected.
+CP_EXPORT cpFloat cpConstraintGetMaxBias(const cpConstraint *constraint);
+/// Set the maximum rate at which joint error is corrected. (defaults to INFINITY)
+CP_EXPORT void cpConstraintSetMaxBias(cpConstraint *constraint, cpFloat maxBias);
+
+/// Get if the two bodies connected by the constraint are allowed to collide or not.
+CP_EXPORT cpBool cpConstraintGetCollideBodies(const cpConstraint *constraint);
+/// Set if the two bodies connected by the constraint are allowed to collide or not. (defaults to cpFalse)
+CP_EXPORT void cpConstraintSetCollideBodies(cpConstraint *constraint, cpBool collideBodies);
+
+/// Get the pre-solve function that is called before the solver runs.
+CP_EXPORT cpConstraintPreSolveFunc cpConstraintGetPreSolveFunc(const cpConstraint *constraint);
+/// Set the pre-solve function that is called before the solver runs.
+CP_EXPORT void cpConstraintSetPreSolveFunc(cpConstraint *constraint, cpConstraintPreSolveFunc preSolveFunc);
+
+/// Get the post-solve function that is called before the solver runs.
+CP_EXPORT cpConstraintPostSolveFunc cpConstraintGetPostSolveFunc(const cpConstraint *constraint);
+/// Set the post-solve function that is called before the solver runs.
+CP_EXPORT void cpConstraintSetPostSolveFunc(cpConstraint *constraint, cpConstraintPostSolveFunc postSolveFunc);
+
+/// Get the user definable data pointer for this constraint
+CP_EXPORT cpDataPointer cpConstraintGetUserData(const cpConstraint *constraint);
+/// Set the user definable data pointer for this constraint
+CP_EXPORT void cpConstraintSetUserData(cpConstraint *constraint, cpDataPointer userData);
+
+/// Get the last impulse applied by this constraint.
+CP_EXPORT cpFloat cpConstraintGetImpulse(cpConstraint *constraint);
+
+#include "cpPinJoint.h"
+#include "cpSlideJoint.h"
+#include "cpPivotJoint.h"
+#include "cpGrooveJoint.h"
+#include "cpDampedSpring.h"
+#include "cpDampedRotarySpring.h"
+#include "cpRotaryLimitJoint.h"
+#include "cpRatchetJoint.h"
+#include "cpGearJoint.h"
+#include "cpSimpleMotor.h"
+
+///@}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpDampedRotarySpring.h b/Chipmunk2D-7.0.2/include/chipmunk/cpDampedRotarySpring.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpDampedRotarySpring.h
@@ -0,0 +1,58 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpDampedRotarySpring cpDampedRotarySpring
+/// @{
+
+/// Check if a constraint is a damped rotary springs.
+CP_EXPORT cpBool cpConstraintIsDampedRotarySpring(const cpConstraint *constraint);
+
+/// Function type used for damped rotary spring force callbacks.
+typedef cpFloat (*cpDampedRotarySpringTorqueFunc)(struct cpConstraint *spring, cpFloat relativeAngle);
+
+/// Allocate a damped rotary spring.
+CP_EXPORT cpDampedRotarySpring* cpDampedRotarySpringAlloc(void);
+/// Initialize a damped rotary spring.
+CP_EXPORT cpDampedRotarySpring* cpDampedRotarySpringInit(cpDampedRotarySpring *joint, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping);
+/// Allocate and initialize a damped rotary spring.
+CP_EXPORT cpConstraint* cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping);
+
+/// Get the rest length of the spring.
+CP_EXPORT cpFloat cpDampedRotarySpringGetRestAngle(const cpConstraint *constraint);
+/// Set the rest length of the spring.
+CP_EXPORT void cpDampedRotarySpringSetRestAngle(cpConstraint *constraint, cpFloat restAngle);
+
+/// Get the stiffness of the spring in force/distance.
+CP_EXPORT cpFloat cpDampedRotarySpringGetStiffness(const cpConstraint *constraint);
+/// Set the stiffness of the spring in force/distance.
+CP_EXPORT void cpDampedRotarySpringSetStiffness(cpConstraint *constraint, cpFloat stiffness);
+
+/// Get the damping of the spring.
+CP_EXPORT cpFloat cpDampedRotarySpringGetDamping(const cpConstraint *constraint);
+/// Set the damping of the spring.
+CP_EXPORT void cpDampedRotarySpringSetDamping(cpConstraint *constraint, cpFloat damping);
+
+/// Get the damping of the spring.
+CP_EXPORT cpDampedRotarySpringTorqueFunc cpDampedRotarySpringGetSpringTorqueFunc(const cpConstraint *constraint);
+/// Set the damping of the spring.
+CP_EXPORT void cpDampedRotarySpringSetSpringTorqueFunc(cpConstraint *constraint, cpDampedRotarySpringTorqueFunc springTorqueFunc);
+
+/// @}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpDampedSpring.h b/Chipmunk2D-7.0.2/include/chipmunk/cpDampedSpring.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpDampedSpring.h
@@ -0,0 +1,68 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpDampedSpring cpDampedSpring
+/// @{
+
+/// Check if a constraint is a slide joint.
+CP_EXPORT cpBool cpConstraintIsDampedSpring(const cpConstraint *constraint);
+
+/// Function type used for damped spring force callbacks.
+typedef cpFloat (*cpDampedSpringForceFunc)(cpConstraint *spring, cpFloat dist);
+
+/// Allocate a damped spring.
+CP_EXPORT cpDampedSpring* cpDampedSpringAlloc(void);
+/// Initialize a damped spring.
+CP_EXPORT cpDampedSpring* cpDampedSpringInit(cpDampedSpring *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat restLength, cpFloat stiffness, cpFloat damping);
+/// Allocate and initialize a damped spring.
+CP_EXPORT cpConstraint* cpDampedSpringNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat restLength, cpFloat stiffness, cpFloat damping);
+
+/// Get the location of the first anchor relative to the first body.
+CP_EXPORT cpVect cpDampedSpringGetAnchorA(const cpConstraint *constraint);
+/// Set the location of the first anchor relative to the first body.
+CP_EXPORT void cpDampedSpringSetAnchorA(cpConstraint *constraint, cpVect anchorA);
+
+/// Get the location of the second anchor relative to the second body.
+CP_EXPORT cpVect cpDampedSpringGetAnchorB(const cpConstraint *constraint);
+/// Set the location of the second anchor relative to the second body.
+CP_EXPORT void cpDampedSpringSetAnchorB(cpConstraint *constraint, cpVect anchorB);
+
+/// Get the rest length of the spring.
+CP_EXPORT cpFloat cpDampedSpringGetRestLength(const cpConstraint *constraint);
+/// Set the rest length of the spring.
+CP_EXPORT void cpDampedSpringSetRestLength(cpConstraint *constraint, cpFloat restLength);
+
+/// Get the stiffness of the spring in force/distance.
+CP_EXPORT cpFloat cpDampedSpringGetStiffness(const cpConstraint *constraint);
+/// Set the stiffness of the spring in force/distance.
+CP_EXPORT void cpDampedSpringSetStiffness(cpConstraint *constraint, cpFloat stiffness);
+
+/// Get the damping of the spring.
+CP_EXPORT cpFloat cpDampedSpringGetDamping(const cpConstraint *constraint);
+/// Set the damping of the spring.
+CP_EXPORT void cpDampedSpringSetDamping(cpConstraint *constraint, cpFloat damping);
+
+/// Get the damping of the spring.
+CP_EXPORT cpDampedSpringForceFunc cpDampedSpringGetSpringForceFunc(const cpConstraint *constraint);
+/// Set the damping of the spring.
+CP_EXPORT void cpDampedSpringSetSpringForceFunc(cpConstraint *constraint, cpDampedSpringForceFunc springForceFunc);
+
+/// @}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpGearJoint.h b/Chipmunk2D-7.0.2/include/chipmunk/cpGearJoint.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpGearJoint.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpGearJoint cpGearJoint
+/// @{
+
+/// Check if a constraint is a damped rotary springs.
+CP_EXPORT cpBool cpConstraintIsGearJoint(const cpConstraint *constraint);
+
+/// Allocate a gear joint.
+CP_EXPORT cpGearJoint* cpGearJointAlloc(void);
+/// Initialize a gear joint.
+CP_EXPORT cpGearJoint* cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio);
+/// Allocate and initialize a gear joint.
+CP_EXPORT cpConstraint* cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio);
+
+/// Get the phase offset of the gears.
+CP_EXPORT cpFloat cpGearJointGetPhase(const cpConstraint *constraint);
+/// Set the phase offset of the gears.
+CP_EXPORT void cpGearJointSetPhase(cpConstraint *constraint, cpFloat phase);
+
+/// Get the angular distance of each ratchet.
+CP_EXPORT cpFloat cpGearJointGetRatio(const cpConstraint *constraint);
+/// Set the ratio of a gear joint.
+CP_EXPORT void cpGearJointSetRatio(cpConstraint *constraint, cpFloat ratio);
+
+/// @}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpGrooveJoint.h b/Chipmunk2D-7.0.2/include/chipmunk/cpGrooveJoint.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpGrooveJoint.h
@@ -0,0 +1,50 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpGrooveJoint cpGrooveJoint
+/// @{
+
+/// Check if a constraint is a slide joint.
+CP_EXPORT cpBool cpConstraintIsGrooveJoint(const cpConstraint *constraint);
+
+/// Allocate a groove joint.
+CP_EXPORT cpGrooveJoint* cpGrooveJointAlloc(void);
+/// Initialize a groove joint.
+CP_EXPORT cpGrooveJoint* cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchorB);
+/// Allocate and initialize a groove joint.
+CP_EXPORT cpConstraint* cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchorB);
+
+/// Get the first endpoint of the groove relative to the first body.
+CP_EXPORT cpVect cpGrooveJointGetGrooveA(const cpConstraint *constraint);
+/// Set the first endpoint of the groove relative to the first body.
+CP_EXPORT void cpGrooveJointSetGrooveA(cpConstraint *constraint, cpVect grooveA);
+
+/// Get the first endpoint of the groove relative to the first body.
+CP_EXPORT cpVect cpGrooveJointGetGrooveB(const cpConstraint *constraint);
+/// Set the first endpoint of the groove relative to the first body.
+CP_EXPORT void cpGrooveJointSetGrooveB(cpConstraint *constraint, cpVect grooveB);
+
+/// Get the location of the second anchor relative to the second body.
+CP_EXPORT cpVect cpGrooveJointGetAnchorB(const cpConstraint *constraint);
+/// Set the location of the second anchor relative to the second body.
+CP_EXPORT void cpGrooveJointSetAnchorB(cpConstraint *constraint, cpVect anchorB);
+
+/// @}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpHastySpace.h b/Chipmunk2D-7.0.2/include/chipmunk/cpHastySpace.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpHastySpace.h
@@ -0,0 +1,27 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+/// cpHastySpace is exclusive to Chipmunk Pro
+/// Currently it enables ARM NEON optimizations in the solver, but in the future will include other optimizations such as
+/// a multi-threaded solver and multi-threaded collision broadphases.
+
+struct cpHastySpace;
+typedef struct cpHastySpace cpHastySpace;
+
+/// Create a new hasty space.
+/// On ARM platforms that support NEON, this will enable the vectorized solver.
+/// cpHastySpace also supports multiple threads, but runs single threaded by default for determinism.
+CP_EXPORT cpSpace *cpHastySpaceNew(void);
+CP_EXPORT void cpHastySpaceFree(cpSpace *space);
+
+/// Set the number of threads to use for the solver.
+/// Currently Chipmunk is limited to 2 threads as using more generally provides very minimal performance gains.
+/// Passing 0 as the thread count on iOS or OS X will cause Chipmunk to automatically detect the number of threads it should use.
+/// On other platforms passing 0 for the thread count will set 1 thread.
+CP_EXPORT void cpHastySpaceSetThreads(cpSpace *space, unsigned long threads);
+
+/// Returns the number of threads the solver is using to run.
+CP_EXPORT unsigned long cpHastySpaceGetThreads(cpSpace *space);
+
+/// When stepping a hasty space, you must use this function.
+CP_EXPORT void cpHastySpaceStep(cpSpace *space, cpFloat dt);
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpMarch.h b/Chipmunk2D-7.0.2/include/chipmunk/cpMarch.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpMarch.h
@@ -0,0 +1,28 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+/// Function type used as a callback from the marching squares algorithm to sample an image function.
+/// It passes you the point to sample and your context pointer, and you return the density.
+typedef cpFloat (*cpMarchSampleFunc)(cpVect point, void *data);
+
+/// Function type used as a callback from the marching squares algorithm to output a line segment.
+/// It passes you the two endpoints and your context pointer.
+typedef void (*cpMarchSegmentFunc)(cpVect v0, cpVect v1, void *data);
+
+/// Trace an anti-aliased contour of an image along a particular threshold.
+/// The given number of samples will be taken and spread across the bounding box area using the sampling function and context.
+/// The segment function will be called for each segment detected that lies along the density contour for @c threshold.
+CP_EXPORT void cpMarchSoft(
+  cpBB bb, unsigned long x_samples, unsigned long y_samples, cpFloat threshold,
+  cpMarchSegmentFunc segment, void *segment_data,
+  cpMarchSampleFunc sample, void *sample_data
+);
+
+/// Trace an aliased curve of an image along a particular threshold.
+/// The given number of samples will be taken and spread across the bounding box area using the sampling function and context.
+/// The segment function will be called for each segment detected that lies along the density contour for @c threshold.
+CP_EXPORT void cpMarchHard(
+  cpBB bb, unsigned long x_samples, unsigned long y_samples, cpFloat threshold,
+  cpMarchSegmentFunc segment, void *segment_data,
+  cpMarchSampleFunc sample, void *sample_data
+);
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpPinJoint.h b/Chipmunk2D-7.0.2/include/chipmunk/cpPinJoint.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpPinJoint.h
@@ -0,0 +1,50 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpPinJoint cpPinJoint
+/// @{
+
+/// Check if a constraint is a pin joint.
+CP_EXPORT cpBool cpConstraintIsPinJoint(const cpConstraint *constraint);
+
+/// Allocate a pin joint.
+CP_EXPORT cpPinJoint* cpPinJointAlloc(void);
+/// Initialize a pin joint.
+CP_EXPORT cpPinJoint* cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB);
+/// Allocate and initialize a pin joint.
+CP_EXPORT cpConstraint* cpPinJointNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB);
+
+/// Get the location of the first anchor relative to the first body.
+CP_EXPORT cpVect cpPinJointGetAnchorA(const cpConstraint *constraint);
+/// Set the location of the first anchor relative to the first body.
+CP_EXPORT void cpPinJointSetAnchorA(cpConstraint *constraint, cpVect anchorA);
+
+/// Get the location of the second anchor relative to the second body.
+CP_EXPORT cpVect cpPinJointGetAnchorB(const cpConstraint *constraint);
+/// Set the location of the second anchor relative to the second body.
+CP_EXPORT void cpPinJointSetAnchorB(cpConstraint *constraint, cpVect anchorB);
+
+/// Get the distance the joint will maintain between the two anchors.
+CP_EXPORT cpFloat cpPinJointGetDist(const cpConstraint *constraint);
+/// Set the distance the joint will maintain between the two anchors.
+CP_EXPORT void cpPinJointSetDist(cpConstraint *constraint, cpFloat dist);
+
+///@}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpPivotJoint.h b/Chipmunk2D-7.0.2/include/chipmunk/cpPivotJoint.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpPivotJoint.h
@@ -0,0 +1,47 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpPivotJoint cpPivotJoint
+/// @{
+
+/// Check if a constraint is a slide joint.
+CP_EXPORT cpBool cpConstraintIsPivotJoint(const cpConstraint *constraint);
+
+/// Allocate a pivot joint
+CP_EXPORT cpPivotJoint* cpPivotJointAlloc(void);
+/// Initialize a pivot joint.
+CP_EXPORT cpPivotJoint* cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB);
+/// Allocate and initialize a pivot joint.
+CP_EXPORT cpConstraint* cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot);
+/// Allocate and initialize a pivot joint with specific anchors.
+CP_EXPORT cpConstraint* cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB);
+
+/// Get the location of the first anchor relative to the first body.
+CP_EXPORT cpVect cpPivotJointGetAnchorA(const cpConstraint *constraint);
+/// Set the location of the first anchor relative to the first body.
+CP_EXPORT void cpPivotJointSetAnchorA(cpConstraint *constraint, cpVect anchorA);
+
+/// Get the location of the second anchor relative to the second body.
+CP_EXPORT cpVect cpPivotJointGetAnchorB(const cpConstraint *constraint);
+/// Set the location of the second anchor relative to the second body.
+CP_EXPORT void cpPivotJointSetAnchorB(cpConstraint *constraint, cpVect anchorB);
+
+/// @}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpPolyShape.h b/Chipmunk2D-7.0.2/include/chipmunk/cpPolyShape.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpPolyShape.h
@@ -0,0 +1,56 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpPolyShape cpPolyShape
+/// @{
+
+/// Allocate a polygon shape.
+CP_EXPORT cpPolyShape* cpPolyShapeAlloc(void);
+/// Initialize a polygon shape with rounded corners.
+/// A convex hull will be created from the vertexes.
+CP_EXPORT cpPolyShape* cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int count, const cpVect *verts, cpTransform transform, cpFloat radius);
+/// Initialize a polygon shape with rounded corners.
+/// The vertexes must be convex with a counter-clockwise winding.
+CP_EXPORT cpPolyShape* cpPolyShapeInitRaw(cpPolyShape *poly, cpBody *body, int count, const cpVect *verts, cpFloat radius);
+/// Allocate and initialize a polygon shape with rounded corners.
+/// A convex hull will be created from the vertexes.
+CP_EXPORT cpShape* cpPolyShapeNew(cpBody *body, int count, const cpVect *verts, cpTransform transform, cpFloat radius);
+/// Allocate and initialize a polygon shape with rounded corners.
+/// The vertexes must be convex with a counter-clockwise winding.
+CP_EXPORT cpShape* cpPolyShapeNewRaw(cpBody *body, int count, const cpVect *verts, cpFloat radius);
+
+/// Initialize a box shaped polygon shape with rounded corners.
+CP_EXPORT cpPolyShape* cpBoxShapeInit(cpPolyShape *poly, cpBody *body, cpFloat width, cpFloat height, cpFloat radius);
+/// Initialize an offset box shaped polygon shape with rounded corners.
+CP_EXPORT cpPolyShape* cpBoxShapeInit2(cpPolyShape *poly, cpBody *body, cpBB box, cpFloat radius);
+/// Allocate and initialize a box shaped polygon shape.
+CP_EXPORT cpShape* cpBoxShapeNew(cpBody *body, cpFloat width, cpFloat height, cpFloat radius);
+/// Allocate and initialize an offset box shaped polygon shape.
+CP_EXPORT cpShape* cpBoxShapeNew2(cpBody *body, cpBB box, cpFloat radius);
+
+/// Get the number of verts in a polygon shape.
+CP_EXPORT int cpPolyShapeGetCount(const cpShape *shape);
+/// Get the @c ith vertex of a polygon shape.
+CP_EXPORT cpVect cpPolyShapeGetVert(const cpShape *shape, int index);
+/// Get the radius of a polygon shape.
+CP_EXPORT cpFloat cpPolyShapeGetRadius(const cpShape *shape);
+
+/// @}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpPolyline.h b/Chipmunk2D-7.0.2/include/chipmunk/cpPolyline.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpPolyline.h
@@ -0,0 +1,70 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+// Polylines are just arrays of vertexes.
+// They are looped if the first vertex is equal to the last.
+// cpPolyline structs are intended to be passed by value and destroyed when you are done with them.
+typedef struct cpPolyline {
+  int count, capacity;
+  cpVect verts[];
+} cpPolyline;
+
+/// Destroy and free a polyline instance.
+CP_EXPORT void cpPolylineFree(cpPolyline *line);
+
+/// Returns true if the first vertex is equal to the last.
+CP_EXPORT cpBool cpPolylineIsClosed(cpPolyline *line);
+
+/**
+	Returns a copy of a polyline simplified by using the Douglas-Peucker algorithm.
+	This works very well on smooth or gently curved shapes, but not well on straight edged or angular shapes.
+*/
+CP_EXPORT cpPolyline *cpPolylineSimplifyCurves(cpPolyline *line, cpFloat tol);
+
+/**
+	Returns a copy of a polyline simplified by discarding "flat" vertexes.
+	This works well on straigt edged or angular shapes, not as well on smooth shapes.
+*/
+CP_EXPORT cpPolyline *cpPolylineSimplifyVertexes(cpPolyline *line, cpFloat tol);
+
+/// Get the convex hull of a polyline as a looped polyline.
+CP_EXPORT cpPolyline *cpPolylineToConvexHull(cpPolyline *line, cpFloat tol);
+
+
+/// Polyline sets are collections of polylines, generally built by cpMarchSoft() or cpMarchHard().
+typedef struct cpPolylineSet {
+  int count, capacity;
+  cpPolyline **lines;
+} cpPolylineSet;
+
+/// Allocate a new polyline set.
+CP_EXPORT cpPolylineSet *cpPolylineSetAlloc(void);
+
+/// Initialize a new polyline set.
+CP_EXPORT cpPolylineSet *cpPolylineSetInit(cpPolylineSet *set);
+
+/// Allocate and initialize a polyline set.
+CP_EXPORT cpPolylineSet *cpPolylineSetNew(void);
+
+/// Destroy a polyline set.
+CP_EXPORT void cpPolylineSetDestroy(cpPolylineSet *set, cpBool freePolylines);
+
+/// Destroy and free a polyline set.
+CP_EXPORT void cpPolylineSetFree(cpPolylineSet *set, cpBool freePolylines);
+
+/**
+	Add a line segment to a polyline set.
+	A segment will either start a new polyline, join two others, or add to or loop an existing polyline.
+	This is mostly intended to be used as a callback directly from cpMarchSoft() or cpMarchHard().
+*/
+CP_EXPORT void cpPolylineSetCollectSegment(cpVect v0, cpVect v1, cpPolylineSet *lines);
+
+/**
+	Get an approximate convex decomposition from a polyline.
+	Returns a cpPolylineSet of convex hulls that match the original shape to within 'tol'.
+	NOTE: If the input is a self intersecting polygon, the output might end up overly simplified.
+*/
+
+CP_EXPORT cpPolylineSet *cpPolylineConvexDecomposition(cpPolyline *line, cpFloat tol);
+
+#define cpPolylineConvexDecomposition_BETA cpPolylineConvexDecomposition
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpRatchetJoint.h b/Chipmunk2D-7.0.2/include/chipmunk/cpRatchetJoint.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpRatchetJoint.h
@@ -0,0 +1,50 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpRatchetJoint cpRatchetJoint
+/// @{
+
+/// Check if a constraint is a damped rotary springs.
+CP_EXPORT cpBool cpConstraintIsRatchetJoint(const cpConstraint *constraint);
+
+/// Allocate a ratchet joint.
+CP_EXPORT cpRatchetJoint* cpRatchetJointAlloc(void);
+/// Initialize a ratched joint.
+CP_EXPORT cpRatchetJoint* cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet);
+/// Allocate and initialize a ratchet joint.
+CP_EXPORT cpConstraint* cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet);
+
+/// Get the angle of the current ratchet tooth.
+CP_EXPORT cpFloat cpRatchetJointGetAngle(const cpConstraint *constraint);
+/// Set the angle of the current ratchet tooth.
+CP_EXPORT void cpRatchetJointSetAngle(cpConstraint *constraint, cpFloat angle);
+
+/// Get the phase offset of the ratchet.
+CP_EXPORT cpFloat cpRatchetJointGetPhase(const cpConstraint *constraint);
+/// Get the phase offset of the ratchet.
+CP_EXPORT void cpRatchetJointSetPhase(cpConstraint *constraint, cpFloat phase);
+
+/// Get the angular distance of each ratchet.
+CP_EXPORT cpFloat cpRatchetJointGetRatchet(const cpConstraint *constraint);
+/// Set the angular distance of each ratchet.
+CP_EXPORT void cpRatchetJointSetRatchet(cpConstraint *constraint, cpFloat ratchet);
+
+/// @}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpRobust.h b/Chipmunk2D-7.0.2/include/chipmunk/cpRobust.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpRobust.h
@@ -0,0 +1,11 @@
+#include "chipmunk/cpVect.h"
+
+// This is a private header for functions (currently just one) that need strict floating point results.
+// It was easier to put this in it's own file than to fiddle with 4 different compiler specific pragmas or attributes.
+// "Fast math" should be disabled here.
+
+// Check if c is to the left of segment (a, b).
+cpBool cpCheckPointGreater(const cpVect a, const cpVect b, const cpVect c);
+
+// Check if p is behind one of v0 or v1 on axis n.
+cpBool cpCheckAxis(cpVect v0, cpVect v1, cpVect p, cpVect n);
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpRotaryLimitJoint.h b/Chipmunk2D-7.0.2/include/chipmunk/cpRotaryLimitJoint.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpRotaryLimitJoint.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpRotaryLimitJoint cpRotaryLimitJoint
+/// @{
+
+/// Check if a constraint is a damped rotary springs.
+CP_EXPORT cpBool cpConstraintIsRotaryLimitJoint(const cpConstraint *constraint);
+
+/// Allocate a damped rotary limit joint.
+CP_EXPORT cpRotaryLimitJoint* cpRotaryLimitJointAlloc(void);
+/// Initialize a damped rotary limit joint.
+CP_EXPORT cpRotaryLimitJoint* cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max);
+/// Allocate and initialize a damped rotary limit joint.
+CP_EXPORT cpConstraint* cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max);
+
+/// Get the minimum distance the joint will maintain between the two anchors.
+CP_EXPORT cpFloat cpRotaryLimitJointGetMin(const cpConstraint *constraint);
+/// Set the minimum distance the joint will maintain between the two anchors.
+CP_EXPORT void cpRotaryLimitJointSetMin(cpConstraint *constraint, cpFloat min);
+
+/// Get the maximum distance the joint will maintain between the two anchors.
+CP_EXPORT cpFloat cpRotaryLimitJointGetMax(const cpConstraint *constraint);
+/// Set the maximum distance the joint will maintain between the two anchors.
+CP_EXPORT void cpRotaryLimitJointSetMax(cpConstraint *constraint, cpFloat max);
+
+/// @}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpShape.h b/Chipmunk2D-7.0.2/include/chipmunk/cpShape.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpShape.h
@@ -0,0 +1,199 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpShape cpShape
+/// The cpShape struct defines the shape of a rigid body.
+/// @{
+
+/// Point query info struct.
+typedef struct cpPointQueryInfo {
+	/// The nearest shape, NULL if no shape was within range.
+	const cpShape *shape;
+	/// The closest point on the shape's surface. (in world space coordinates)
+	cpVect point;
+	/// The distance to the point. The distance is negative if the point is inside the shape.
+	cpFloat distance;
+	/// The gradient of the signed distance function.
+	/// The value should be similar to info.p/info.d, but accurate even for very small values of info.d.
+	cpVect gradient;
+} cpPointQueryInfo;
+
+/// Segment query info struct.
+typedef struct cpSegmentQueryInfo {
+	/// The shape that was hit, or NULL if no collision occured.
+	const cpShape *shape;
+	/// The point of impact.
+	cpVect point;
+	/// The normal of the surface hit.
+	cpVect normal;
+	/// The normalized distance along the query segment in the range [0, 1].
+	cpFloat alpha;
+} cpSegmentQueryInfo;
+
+/// Fast collision filtering type that is used to determine if two objects collide before calling collision or query callbacks.
+typedef struct cpShapeFilter {
+	/// Two objects with the same non-zero group value do not collide.
+	/// This is generally used to group objects in a composite object together to disable self collisions.
+	cpGroup group;
+	/// A bitmask of user definable categories that this object belongs to.
+	/// The category/mask combinations of both objects in a collision must agree for a collision to occur.
+	cpBitmask categories;
+	/// A bitmask of user definable category types that this object object collides with.
+	/// The category/mask combinations of both objects in a collision must agree for a collision to occur.
+	cpBitmask mask;
+} cpShapeFilter;
+
+/// Collision filter value for a shape that will collide with anything except CP_SHAPE_FILTER_NONE.
+static const cpShapeFilter CP_SHAPE_FILTER_ALL = {CP_NO_GROUP, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES};
+/// Collision filter value for a shape that does not collide with anything.
+static const cpShapeFilter CP_SHAPE_FILTER_NONE = {CP_NO_GROUP, ~CP_ALL_CATEGORIES, ~CP_ALL_CATEGORIES};
+
+/// Create a new collision filter.
+static inline cpShapeFilter
+cpShapeFilterNew(cpGroup group, cpBitmask categories, cpBitmask mask)
+{
+	cpShapeFilter filter = {group, categories, mask};
+	return filter;
+}
+
+/// Destroy a shape.
+CP_EXPORT void cpShapeDestroy(cpShape *shape);
+/// Destroy and Free a shape.
+CP_EXPORT void cpShapeFree(cpShape *shape);
+
+/// Update, cache and return the bounding box of a shape based on the body it's attached to.
+CP_EXPORT cpBB cpShapeCacheBB(cpShape *shape);
+/// Update, cache and return the bounding box of a shape with an explicit transformation.
+CP_EXPORT cpBB cpShapeUpdate(cpShape *shape, cpTransform transform);
+
+/// Perform a nearest point query. It finds the closest point on the surface of shape to a specific point.
+/// The value returned is the distance between the points. A negative distance means the point is inside the shape.
+CP_EXPORT cpFloat cpShapePointQuery(const cpShape *shape, cpVect p, cpPointQueryInfo *out);
+
+/// Perform a segment query against a shape. @c info must be a pointer to a valid cpSegmentQueryInfo structure.
+CP_EXPORT cpBool cpShapeSegmentQuery(const cpShape *shape, cpVect a, cpVect b, cpFloat radius, cpSegmentQueryInfo *info);
+
+/// Return contact information about two shapes.
+CP_EXPORT cpContactPointSet cpShapesCollide(const cpShape *a, const cpShape *b);
+
+/// The cpSpace this body is added to.
+CP_EXPORT cpSpace* cpShapeGetSpace(const cpShape *shape);
+
+/// The cpBody this shape is connected to.
+CP_EXPORT cpBody* cpShapeGetBody(const cpShape *shape);
+/// Set the cpBody this shape is connected to.
+/// Can only be used if the shape is not currently added to a space.
+CP_EXPORT void cpShapeSetBody(cpShape *shape, cpBody *body);
+
+/// Get the mass of the shape if you are having Chipmunk calculate mass properties for you.
+CP_EXPORT cpFloat cpShapeGetMass(cpShape *shape);
+/// Set the mass of this shape to have Chipmunk calculate mass properties for you.
+CP_EXPORT void cpShapeSetMass(cpShape *shape, cpFloat mass);
+
+/// Get the density of the shape if you are having Chipmunk calculate mass properties for you.
+CP_EXPORT cpFloat cpShapeGetDensity(cpShape *shape);
+/// Set the density  of this shape to have Chipmunk calculate mass properties for you.
+CP_EXPORT void cpShapeSetDensity(cpShape *shape, cpFloat density);
+
+/// Get the calculated moment of inertia for this shape.
+CP_EXPORT cpFloat cpShapeGetMoment(cpShape *shape);
+/// Get the calculated area of this shape.
+CP_EXPORT cpFloat cpShapeGetArea(cpShape *shape);
+/// Get the centroid of this shape.
+CP_EXPORT cpVect cpShapeGetCenterOfGravity(cpShape *shape);
+
+/// Get the bounding box that contains the shape given it's current position and angle.
+CP_EXPORT cpBB cpShapeGetBB(const cpShape *shape);
+
+/// Get if the shape is set to be a sensor or not.
+CP_EXPORT cpBool cpShapeGetSensor(const cpShape *shape);
+/// Set if the shape is a sensor or not.
+CP_EXPORT void cpShapeSetSensor(cpShape *shape, cpBool sensor);
+
+/// Get the elasticity of this shape.
+CP_EXPORT cpFloat cpShapeGetElasticity(const cpShape *shape);
+/// Set the elasticity of this shape.
+CP_EXPORT void cpShapeSetElasticity(cpShape *shape, cpFloat elasticity);
+
+/// Get the friction of this shape.
+CP_EXPORT cpFloat cpShapeGetFriction(const cpShape *shape);
+/// Set the friction of this shape.
+CP_EXPORT void cpShapeSetFriction(cpShape *shape, cpFloat friction);
+
+/// Get the surface velocity of this shape.
+CP_EXPORT cpVect cpShapeGetSurfaceVelocity(const cpShape *shape);
+/// Set the surface velocity of this shape.
+CP_EXPORT void cpShapeSetSurfaceVelocity(cpShape *shape, cpVect surfaceVelocity);
+
+/// Get the user definable data pointer of this shape.
+CP_EXPORT cpDataPointer cpShapeGetUserData(const cpShape *shape);
+/// Set the user definable data pointer of this shape.
+CP_EXPORT void cpShapeSetUserData(cpShape *shape, cpDataPointer userData);
+
+/// Set the collision type of this shape.
+CP_EXPORT cpCollisionType cpShapeGetCollisionType(const cpShape *shape);
+/// Get the collision type of this shape.
+CP_EXPORT void cpShapeSetCollisionType(cpShape *shape, cpCollisionType collisionType);
+
+/// Get the collision filtering parameters of this shape.
+CP_EXPORT cpShapeFilter cpShapeGetFilter(const cpShape *shape);
+/// Set the collision filtering parameters of this shape.
+CP_EXPORT void cpShapeSetFilter(cpShape *shape, cpShapeFilter filter);
+
+
+/// @}
+/// @defgroup cpCircleShape cpCircleShape
+
+/// Allocate a circle shape.
+CP_EXPORT cpCircleShape* cpCircleShapeAlloc(void);
+/// Initialize a circle shape.
+CP_EXPORT cpCircleShape* cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset);
+/// Allocate and initialize a circle shape.
+CP_EXPORT cpShape* cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset);
+
+/// Get the offset of a circle shape.
+CP_EXPORT cpVect cpCircleShapeGetOffset(const cpShape *shape);
+/// Get the radius of a circle shape.
+CP_EXPORT cpFloat cpCircleShapeGetRadius(const cpShape *shape);
+
+/// @}
+/// @defgroup cpSegmentShape cpSegmentShape
+
+/// Allocate a segment shape.
+CP_EXPORT cpSegmentShape* cpSegmentShapeAlloc(void);
+/// Initialize a segment shape.
+CP_EXPORT cpSegmentShape* cpSegmentShapeInit(cpSegmentShape *seg, cpBody *body, cpVect a, cpVect b, cpFloat radius);
+/// Allocate and initialize a segment shape.
+CP_EXPORT cpShape* cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat radius);
+
+/// Let Chipmunk know about the geometry of adjacent segments to avoid colliding with endcaps.
+CP_EXPORT void cpSegmentShapeSetNeighbors(cpShape *shape, cpVect prev, cpVect next);
+
+/// Get the first endpoint of a segment shape.
+CP_EXPORT cpVect cpSegmentShapeGetA(const cpShape *shape);
+/// Get the second endpoint of a segment shape.
+CP_EXPORT cpVect cpSegmentShapeGetB(const cpShape *shape);
+/// Get the normal of a segment shape.
+CP_EXPORT cpVect cpSegmentShapeGetNormal(const cpShape *shape);
+/// Get the first endpoint of a segment shape.
+CP_EXPORT cpFloat cpSegmentShapeGetRadius(const cpShape *shape);
+
+/// @}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpSimpleMotor.h b/Chipmunk2D-7.0.2/include/chipmunk/cpSimpleMotor.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpSimpleMotor.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpSimpleMotor cpSimpleMotor
+/// @{
+
+/// Opaque struct type for damped rotary springs.
+typedef struct cpSimpleMotor cpSimpleMotor;
+
+/// Check if a constraint is a damped rotary springs.
+CP_EXPORT cpBool cpConstraintIsSimpleMotor(const cpConstraint *constraint);
+
+/// Allocate a simple motor.
+CP_EXPORT cpSimpleMotor* cpSimpleMotorAlloc(void);
+/// initialize a simple motor.
+CP_EXPORT cpSimpleMotor* cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate);
+/// Allocate and initialize a simple motor.
+CP_EXPORT cpConstraint* cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate);
+
+/// Get the rate of the motor.
+CP_EXPORT cpFloat cpSimpleMotorGetRate(const cpConstraint *constraint);
+/// Set the rate of the motor.
+CP_EXPORT void cpSimpleMotorSetRate(cpConstraint *constraint, cpFloat rate);
+
+/// @}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpSlideJoint.h b/Chipmunk2D-7.0.2/include/chipmunk/cpSlideJoint.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpSlideJoint.h
@@ -0,0 +1,55 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpSlideJoint cpSlideJoint
+/// @{
+
+/// Check if a constraint is a slide joint.
+CP_EXPORT cpBool cpConstraintIsSlideJoint(const cpConstraint *constraint);
+
+/// Allocate a slide joint.
+CP_EXPORT cpSlideJoint* cpSlideJointAlloc(void);
+/// Initialize a slide joint.
+CP_EXPORT cpSlideJoint* cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat min, cpFloat max);
+/// Allocate and initialize a slide joint.
+CP_EXPORT cpConstraint* cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat min, cpFloat max);
+
+/// Get the location of the first anchor relative to the first body.
+CP_EXPORT cpVect cpSlideJointGetAnchorA(const cpConstraint *constraint);
+/// Set the location of the first anchor relative to the first body.
+CP_EXPORT void cpSlideJointSetAnchorA(cpConstraint *constraint, cpVect anchorA);
+
+/// Get the location of the second anchor relative to the second body.
+CP_EXPORT cpVect cpSlideJointGetAnchorB(const cpConstraint *constraint);
+/// Set the location of the second anchor relative to the second body.
+CP_EXPORT void cpSlideJointSetAnchorB(cpConstraint *constraint, cpVect anchorB);
+
+/// Get the minimum distance the joint will maintain between the two anchors.
+CP_EXPORT cpFloat cpSlideJointGetMin(const cpConstraint *constraint);
+/// Set the minimum distance the joint will maintain between the two anchors.
+CP_EXPORT void cpSlideJointSetMin(cpConstraint *constraint, cpFloat min);
+
+/// Get the maximum distance the joint will maintain between the two anchors.
+CP_EXPORT cpFloat cpSlideJointGetMax(const cpConstraint *constraint);
+/// Set the maximum distance the joint will maintain between the two anchors.
+CP_EXPORT void cpSlideJointSetMax(cpConstraint *constraint, cpFloat max);
+
+/// @}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpSpace.h b/Chipmunk2D-7.0.2/include/chipmunk/cpSpace.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpSpace.h
@@ -0,0 +1,319 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpSpace cpSpace
+/// @{
+
+//MARK: Definitions
+
+/// Collision begin event function callback type.
+/// Returning false from a begin callback causes the collision to be ignored until
+/// the the separate callback is called when the objects stop colliding.
+typedef cpBool (*cpCollisionBeginFunc)(cpArbiter *arb, cpSpace *space, cpDataPointer userData);
+/// Collision pre-solve event function callback type.
+/// Returning false from a pre-step callback causes the collision to be ignored until the next step.
+typedef cpBool (*cpCollisionPreSolveFunc)(cpArbiter *arb, cpSpace *space, cpDataPointer userData);
+/// Collision post-solve event function callback type.
+typedef void (*cpCollisionPostSolveFunc)(cpArbiter *arb, cpSpace *space, cpDataPointer userData);
+/// Collision separate event function callback type.
+typedef void (*cpCollisionSeparateFunc)(cpArbiter *arb, cpSpace *space, cpDataPointer userData);
+
+/// Struct that holds function callback pointers to configure custom collision handling.
+/// Collision handlers have a pair of types; when a collision occurs between two shapes that have these types, the collision handler functions are triggered.
+struct cpCollisionHandler {
+	/// Collision type identifier of the first shape that this handler recognizes.
+	/// In the collision handler callback, the shape with this type will be the first argument. Read only.
+	const cpCollisionType typeA;
+	/// Collision type identifier of the second shape that this handler recognizes.
+	/// In the collision handler callback, the shape with this type will be the second argument. Read only.
+	const cpCollisionType typeB;
+	/// This function is called when two shapes with types that match this collision handler begin colliding.
+	cpCollisionBeginFunc beginFunc;
+	/// This function is called each step when two shapes with types that match this collision handler are colliding.
+	/// It's called before the collision solver runs so that you can affect a collision's outcome.
+	cpCollisionPreSolveFunc preSolveFunc;
+	/// This function is called each step when two shapes with types that match this collision handler are colliding.
+	/// It's called after the collision solver runs so that you can read back information about the collision to trigger events in your game.
+	cpCollisionPostSolveFunc postSolveFunc;
+	/// This function is called when two shapes with types that match this collision handler stop colliding.
+	cpCollisionSeparateFunc separateFunc;
+	/// This is a user definable context pointer that is passed to all of the collision handler functions.
+	cpDataPointer userData;
+};
+
+// TODO: Make timestep a parameter?
+
+
+//MARK: Memory and Initialization
+
+/// Allocate a cpSpace.
+CP_EXPORT cpSpace* cpSpaceAlloc(void);
+/// Initialize a cpSpace.
+CP_EXPORT cpSpace* cpSpaceInit(cpSpace *space);
+/// Allocate and initialize a cpSpace.
+CP_EXPORT cpSpace* cpSpaceNew(void);
+
+/// Destroy a cpSpace.
+CP_EXPORT void cpSpaceDestroy(cpSpace *space);
+/// Destroy and free a cpSpace.
+CP_EXPORT void cpSpaceFree(cpSpace *space);
+
+
+//MARK: Properties
+
+/// Number of iterations to use in the impulse solver to solve contacts and other constraints.
+CP_EXPORT int cpSpaceGetIterations(const cpSpace *space);
+CP_EXPORT void cpSpaceSetIterations(cpSpace *space, int iterations);
+
+/// Gravity to pass to rigid bodies when integrating velocity.
+CP_EXPORT cpVect cpSpaceGetGravity(const cpSpace *space);
+CP_EXPORT void cpSpaceSetGravity(cpSpace *space, cpVect gravity);
+
+/// Damping rate expressed as the fraction of velocity bodies retain each second.
+/// A value of 0.9 would mean that each body's velocity will drop 10% per second.
+/// The default value is 1.0, meaning no damping is applied.
+/// @note This damping value is different than those of cpDampedSpring and cpDampedRotarySpring.
+CP_EXPORT cpFloat cpSpaceGetDamping(const cpSpace *space);
+CP_EXPORT void cpSpaceSetDamping(cpSpace *space, cpFloat damping);
+
+/// Speed threshold for a body to be considered idle.
+/// The default value of 0 means to let the space guess a good threshold based on gravity.
+CP_EXPORT cpFloat cpSpaceGetIdleSpeedThreshold(const cpSpace *space);
+CP_EXPORT void cpSpaceSetIdleSpeedThreshold(cpSpace *space, cpFloat idleSpeedThreshold);
+
+/// Time a group of bodies must remain idle in order to fall asleep.
+/// Enabling sleeping also implicitly enables the the contact graph.
+/// The default value of INFINITY disables the sleeping algorithm.
+CP_EXPORT cpFloat cpSpaceGetSleepTimeThreshold(const cpSpace *space);
+CP_EXPORT void cpSpaceSetSleepTimeThreshold(cpSpace *space, cpFloat sleepTimeThreshold);
+
+/// Amount of encouraged penetration between colliding shapes.
+/// Used to reduce oscillating contacts and keep the collision cache warm.
+/// Defaults to 0.1. If you have poor simulation quality,
+/// increase this number as much as possible without allowing visible amounts of overlap.
+CP_EXPORT cpFloat cpSpaceGetCollisionSlop(const cpSpace *space);
+CP_EXPORT void cpSpaceSetCollisionSlop(cpSpace *space, cpFloat collisionSlop);
+
+/// Determines how fast overlapping shapes are pushed apart.
+/// Expressed as a fraction of the error remaining after each second.
+/// Defaults to pow(1.0 - 0.1, 60.0) meaning that Chipmunk fixes 10% of overlap each frame at 60Hz.
+CP_EXPORT cpFloat cpSpaceGetCollisionBias(const cpSpace *space);
+CP_EXPORT void cpSpaceSetCollisionBias(cpSpace *space, cpFloat collisionBias);
+
+/// Number of frames that contact information should persist.
+/// Defaults to 3. There is probably never a reason to change this value.
+CP_EXPORT cpTimestamp cpSpaceGetCollisionPersistence(const cpSpace *space);
+CP_EXPORT void cpSpaceSetCollisionPersistence(cpSpace *space, cpTimestamp collisionPersistence);
+
+/// User definable data pointer.
+/// Generally this points to your game's controller or game state
+/// class so you can access it when given a cpSpace reference in a callback.
+CP_EXPORT cpDataPointer cpSpaceGetUserData(const cpSpace *space);
+CP_EXPORT void cpSpaceSetUserData(cpSpace *space, cpDataPointer userData);
+
+/// The Space provided static body for a given cpSpace.
+/// This is merely provided for convenience and you are not required to use it.
+CP_EXPORT cpBody* cpSpaceGetStaticBody(const cpSpace *space);
+
+/// Returns the current (or most recent) time step used with the given space.
+/// Useful from callbacks if your time step is not a compile-time global.
+CP_EXPORT cpFloat cpSpaceGetCurrentTimeStep(const cpSpace *space);
+
+/// returns true from inside a callback when objects cannot be added/removed.
+CP_EXPORT cpBool cpSpaceIsLocked(cpSpace *space);
+
+
+//MARK: Collision Handlers
+
+/// Create or return the existing collision handler that is called for all collisions that are not handled by a more specific collision handler.
+CP_EXPORT cpCollisionHandler *cpSpaceAddDefaultCollisionHandler(cpSpace *space);
+/// Create or return the existing collision handler for the specified pair of collision types.
+/// If wildcard handlers are used with either of the collision types, it's the responibility of the custom handler to invoke the wildcard handlers.
+CP_EXPORT cpCollisionHandler *cpSpaceAddCollisionHandler(cpSpace *space, cpCollisionType a, cpCollisionType b);
+/// Create or return the existing wildcard collision handler for the specified type.
+CP_EXPORT cpCollisionHandler *cpSpaceAddWildcardHandler(cpSpace *space, cpCollisionType type);
+
+
+//MARK: Add/Remove objects
+
+/// Add a collision shape to the simulation.
+/// If the shape is attached to a static body, it will be added as a static shape.
+CP_EXPORT cpShape* cpSpaceAddShape(cpSpace *space, cpShape *shape);
+/// Add a rigid body to the simulation.
+CP_EXPORT cpBody* cpSpaceAddBody(cpSpace *space, cpBody *body);
+/// Add a constraint to the simulation.
+CP_EXPORT cpConstraint* cpSpaceAddConstraint(cpSpace *space, cpConstraint *constraint);
+
+/// Remove a collision shape from the simulation.
+CP_EXPORT void cpSpaceRemoveShape(cpSpace *space, cpShape *shape);
+/// Remove a rigid body from the simulation.
+CP_EXPORT void cpSpaceRemoveBody(cpSpace *space, cpBody *body);
+/// Remove a constraint from the simulation.
+CP_EXPORT void cpSpaceRemoveConstraint(cpSpace *space, cpConstraint *constraint);
+
+/// Test if a collision shape has been added to the space.
+CP_EXPORT cpBool cpSpaceContainsShape(cpSpace *space, cpShape *shape);
+/// Test if a rigid body has been added to the space.
+CP_EXPORT cpBool cpSpaceContainsBody(cpSpace *space, cpBody *body);
+/// Test if a constraint has been added to the space.
+CP_EXPORT cpBool cpSpaceContainsConstraint(cpSpace *space, cpConstraint *constraint);
+
+//MARK: Post-Step Callbacks
+
+/// Post Step callback function type.
+typedef void (*cpPostStepFunc)(cpSpace *space, void *key, void *data);
+/// Schedule a post-step callback to be called when cpSpaceStep() finishes.
+/// You can only register one callback per unique value for @c key.
+/// Returns true only if @c key has never been scheduled before.
+/// It's possible to pass @c NULL for @c func if you only want to mark @c key as being used.
+CP_EXPORT cpBool cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *key, void *data);
+
+
+//MARK: Queries
+
+// TODO: Queries and iterators should take a cpSpace parametery.
+// TODO: They should also be abortable.
+
+/// Nearest point query callback function type.
+typedef void (*cpSpacePointQueryFunc)(cpShape *shape, cpVect point, cpFloat distance, cpVect gradient, void *data);
+/// Query the space at a point and call @c func for each shape found.
+CP_EXPORT void cpSpacePointQuery(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpSpacePointQueryFunc func, void *data);
+/// Query the space at a point and return the nearest shape found. Returns NULL if no shapes were found.
+CP_EXPORT cpShape *cpSpacePointQueryNearest(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpPointQueryInfo *out);
+
+/// Segment query callback function type.
+typedef void (*cpSpaceSegmentQueryFunc)(cpShape *shape, cpVect point, cpVect normal, cpFloat alpha, void *data);
+/// Perform a directed line segment query (like a raycast) against the space calling @c func for each shape intersected.
+CP_EXPORT void cpSpaceSegmentQuery(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSpaceSegmentQueryFunc func, void *data);
+/// Perform a directed line segment query (like a raycast) against the space and return the first shape hit. Returns NULL if no shapes were hit.
+CP_EXPORT cpShape *cpSpaceSegmentQueryFirst(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSegmentQueryInfo *out);
+
+/// Rectangle Query callback function type.
+typedef void (*cpSpaceBBQueryFunc)(cpShape *shape, void *data);
+/// Perform a fast rectangle query on the space calling @c func for each shape found.
+/// Only the shape's bounding boxes are checked for overlap, not their full shape.
+CP_EXPORT void cpSpaceBBQuery(cpSpace *space, cpBB bb, cpShapeFilter filter, cpSpaceBBQueryFunc func, void *data);
+
+/// Shape query callback function type.
+typedef void (*cpSpaceShapeQueryFunc)(cpShape *shape, cpContactPointSet *points, void *data);
+/// Query a space for any shapes overlapping the given shape and call @c func for each shape found.
+CP_EXPORT cpBool cpSpaceShapeQuery(cpSpace *space, cpShape *shape, cpSpaceShapeQueryFunc func, void *data);
+
+
+//MARK: Iteration
+
+/// Space/body iterator callback function type.
+typedef void (*cpSpaceBodyIteratorFunc)(cpBody *body, void *data);
+/// Call @c func for each body in the space.
+CP_EXPORT void cpSpaceEachBody(cpSpace *space, cpSpaceBodyIteratorFunc func, void *data);
+
+/// Space/body iterator callback function type.
+typedef void (*cpSpaceShapeIteratorFunc)(cpShape *shape, void *data);
+/// Call @c func for each shape in the space.
+CP_EXPORT void cpSpaceEachShape(cpSpace *space, cpSpaceShapeIteratorFunc func, void *data);
+
+/// Space/constraint iterator callback function type.
+typedef void (*cpSpaceConstraintIteratorFunc)(cpConstraint *constraint, void *data);
+/// Call @c func for each shape in the space.
+CP_EXPORT void cpSpaceEachConstraint(cpSpace *space, cpSpaceConstraintIteratorFunc func, void *data);
+
+
+//MARK: Indexing
+
+/// Update the collision detection info for the static shapes in the space.
+CP_EXPORT void cpSpaceReindexStatic(cpSpace *space);
+/// Update the collision detection data for a specific shape in the space.
+CP_EXPORT void cpSpaceReindexShape(cpSpace *space, cpShape *shape);
+/// Update the collision detection data for all shapes attached to a body.
+CP_EXPORT void cpSpaceReindexShapesForBody(cpSpace *space, cpBody *body);
+
+/// Switch the space to use a spatial has as it's spatial index.
+CP_EXPORT void cpSpaceUseSpatialHash(cpSpace *space, cpFloat dim, int count);
+
+
+//MARK: Time Stepping
+
+/// Step the space forward in time by @c dt.
+CP_EXPORT void cpSpaceStep(cpSpace *space, cpFloat dt);
+
+
+//MARK: Debug API
+
+#ifndef CP_SPACE_DISABLE_DEBUG_API
+
+/// Color type to use with the space debug drawing API.
+typedef struct cpSpaceDebugColor {
+	float r, g, b, a;
+} cpSpaceDebugColor;
+
+/// Callback type for a function that draws a filled, stroked circle.
+typedef void (*cpSpaceDebugDrawCircleImpl)(cpVect pos, cpFloat angle, cpFloat radius, cpSpaceDebugColor outlineColor, cpSpaceDebugColor fillColor, cpDataPointer data);
+/// Callback type for a function that draws a line segment.
+typedef void (*cpSpaceDebugDrawSegmentImpl)(cpVect a, cpVect b, cpSpaceDebugColor color, cpDataPointer data);
+/// Callback type for a function that draws a thick line segment.
+typedef void (*cpSpaceDebugDrawFatSegmentImpl)(cpVect a, cpVect b, cpFloat radius, cpSpaceDebugColor outlineColor, cpSpaceDebugColor fillColor, cpDataPointer data);
+/// Callback type for a function that draws a convex polygon.
+typedef void (*cpSpaceDebugDrawPolygonImpl)(int count, const cpVect *verts, cpFloat radius, cpSpaceDebugColor outlineColor, cpSpaceDebugColor fillColor, cpDataPointer data);
+/// Callback type for a function that draws a dot.
+typedef void (*cpSpaceDebugDrawDotImpl)(cpFloat size, cpVect pos, cpSpaceDebugColor color, cpDataPointer data);
+/// Callback type for a function that returns a color for a given shape. This gives you an opportunity to color shapes based on how they are used in your engine.
+typedef cpSpaceDebugColor (*cpSpaceDebugDrawColorForShapeImpl)(cpShape *shape, cpDataPointer data);
+
+typedef enum cpSpaceDebugDrawFlags {
+	CP_SPACE_DEBUG_DRAW_SHAPES = 1<<0,
+	CP_SPACE_DEBUG_DRAW_CONSTRAINTS = 1<<1,
+	CP_SPACE_DEBUG_DRAW_COLLISION_POINTS = 1<<2,
+} cpSpaceDebugDrawFlags;
+
+/// Struct used with cpSpaceDebugDraw() containing drawing callbacks and other drawing settings.
+typedef struct cpSpaceDebugDrawOptions {
+	/// Function that will be invoked to draw circles.
+	cpSpaceDebugDrawCircleImpl drawCircle;
+	/// Function that will be invoked to draw line segments.
+	cpSpaceDebugDrawSegmentImpl drawSegment;
+	/// Function that will be invoked to draw thick line segments.
+	cpSpaceDebugDrawFatSegmentImpl drawFatSegment;
+	/// Function that will be invoked to draw convex polygons.
+	cpSpaceDebugDrawPolygonImpl drawPolygon;
+	/// Function that will be invoked to draw dots.
+	cpSpaceDebugDrawDotImpl drawDot;
+	
+	/// Flags that request which things to draw (collision shapes, constraints, contact points).
+	cpSpaceDebugDrawFlags flags;
+	/// Outline color passed to the drawing function.
+	cpSpaceDebugColor shapeOutlineColor;
+	/// Function that decides what fill color to draw shapes using.
+	cpSpaceDebugDrawColorForShapeImpl colorForShape;
+	/// Color passed to drawing functions for constraints.
+	cpSpaceDebugColor constraintColor;
+	/// Color passed to drawing functions for collision points.
+	cpSpaceDebugColor collisionPointColor;
+	
+	/// User defined context pointer passed to all of the callback functions as the 'data' argument.
+	cpDataPointer data;
+} cpSpaceDebugDrawOptions;
+
+/// Debug draw the current state of the space using the supplied drawing options.
+CP_EXPORT void cpSpaceDebugDraw(cpSpace *space, cpSpaceDebugDrawOptions *options);
+
+#endif
+
+/// @}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpSpatialIndex.h b/Chipmunk2D-7.0.2/include/chipmunk/cpSpatialIndex.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpSpatialIndex.h
@@ -0,0 +1,227 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+	@defgroup cpSpatialIndex cpSpatialIndex
+	
+	Spatial indexes are data structures that are used to accelerate collision detection
+	and spatial queries. Chipmunk provides a number of spatial index algorithms to pick from
+	and they are programmed in a generic way so that you can use them for holding more than
+	just cpShape structs.
+	
+	It works by using @c void pointers to the objects you add and using a callback to ask your code
+	for bounding boxes when it needs them. Several types of queries can be performed an index as well
+	as reindexing and full collision information. All communication to the spatial indexes is performed
+	through callback functions.
+	
+	Spatial indexes should be treated as opaque structs.
+	This meanns you shouldn't be reading any of the struct fields.
+	@{
+*/
+
+//MARK: Spatial Index
+
+/// Spatial index bounding box callback function type.
+/// The spatial index calls this function and passes you a pointer to an object you added
+/// when it needs to get the bounding box associated with that object.
+typedef cpBB (*cpSpatialIndexBBFunc)(void *obj);
+/// Spatial index/object iterator callback function type.
+typedef void (*cpSpatialIndexIteratorFunc)(void *obj, void *data);
+/// Spatial query callback function type.
+typedef cpCollisionID (*cpSpatialIndexQueryFunc)(void *obj1, void *obj2, cpCollisionID id, void *data);
+/// Spatial segment query callback function type.
+typedef cpFloat (*cpSpatialIndexSegmentQueryFunc)(void *obj1, void *obj2, void *data);
+
+
+typedef struct cpSpatialIndexClass cpSpatialIndexClass;
+typedef struct cpSpatialIndex cpSpatialIndex;
+
+/// @private
+struct cpSpatialIndex {
+	cpSpatialIndexClass *klass;
+	
+	cpSpatialIndexBBFunc bbfunc;
+	
+	cpSpatialIndex *staticIndex, *dynamicIndex;
+};
+
+
+//MARK: Spatial Hash
+
+typedef struct cpSpaceHash cpSpaceHash;
+
+/// Allocate a spatial hash.
+CP_EXPORT cpSpaceHash* cpSpaceHashAlloc(void);
+/// Initialize a spatial hash. 
+CP_EXPORT cpSpatialIndex* cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int numcells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
+/// Allocate and initialize a spatial hash.
+CP_EXPORT cpSpatialIndex* cpSpaceHashNew(cpFloat celldim, int cells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
+
+/// Change the cell dimensions and table size of the spatial hash to tune it.
+/// The cell dimensions should roughly match the average size of your objects
+/// and the table size should be ~10 larger than the number of objects inserted.
+/// Some trial and error is required to find the optimum numbers for efficiency.
+CP_EXPORT void cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells);
+
+//MARK: AABB Tree
+
+typedef struct cpBBTree cpBBTree;
+
+/// Allocate a bounding box tree.
+CP_EXPORT cpBBTree* cpBBTreeAlloc(void);
+/// Initialize a bounding box tree.
+CP_EXPORT cpSpatialIndex* cpBBTreeInit(cpBBTree *tree, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
+/// Allocate and initialize a bounding box tree.
+CP_EXPORT cpSpatialIndex* cpBBTreeNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
+
+/// Perform a static top down optimization of the tree.
+CP_EXPORT void cpBBTreeOptimize(cpSpatialIndex *index);
+
+/// Bounding box tree velocity callback function.
+/// This function should return an estimate for the object's velocity.
+typedef cpVect (*cpBBTreeVelocityFunc)(void *obj);
+/// Set the velocity function for the bounding box tree to enable temporal coherence.
+CP_EXPORT void cpBBTreeSetVelocityFunc(cpSpatialIndex *index, cpBBTreeVelocityFunc func);
+
+//MARK: Single Axis Sweep
+
+typedef struct cpSweep1D cpSweep1D;
+
+/// Allocate a 1D sort and sweep broadphase.
+CP_EXPORT cpSweep1D* cpSweep1DAlloc(void);
+/// Initialize a 1D sort and sweep broadphase.
+CP_EXPORT cpSpatialIndex* cpSweep1DInit(cpSweep1D *sweep, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
+/// Allocate and initialize a 1D sort and sweep broadphase.
+CP_EXPORT cpSpatialIndex* cpSweep1DNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
+
+//MARK: Spatial Index Implementation
+
+typedef void (*cpSpatialIndexDestroyImpl)(cpSpatialIndex *index);
+
+typedef int (*cpSpatialIndexCountImpl)(cpSpatialIndex *index);
+typedef void (*cpSpatialIndexEachImpl)(cpSpatialIndex *index, cpSpatialIndexIteratorFunc func, void *data);
+
+typedef cpBool (*cpSpatialIndexContainsImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid);
+typedef void (*cpSpatialIndexInsertImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid);
+typedef void (*cpSpatialIndexRemoveImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid);
+
+typedef void (*cpSpatialIndexReindexImpl)(cpSpatialIndex *index);
+typedef void (*cpSpatialIndexReindexObjectImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid);
+typedef void (*cpSpatialIndexReindexQueryImpl)(cpSpatialIndex *index, cpSpatialIndexQueryFunc func, void *data);
+
+typedef void (*cpSpatialIndexQueryImpl)(cpSpatialIndex *index, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data);
+typedef void (*cpSpatialIndexSegmentQueryImpl)(cpSpatialIndex *index, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data);
+
+struct cpSpatialIndexClass {
+	cpSpatialIndexDestroyImpl destroy;
+	
+	cpSpatialIndexCountImpl count;
+	cpSpatialIndexEachImpl each;
+	
+	cpSpatialIndexContainsImpl contains;
+	cpSpatialIndexInsertImpl insert;
+	cpSpatialIndexRemoveImpl remove;
+	
+	cpSpatialIndexReindexImpl reindex;
+	cpSpatialIndexReindexObjectImpl reindexObject;
+	cpSpatialIndexReindexQueryImpl reindexQuery;
+	
+	cpSpatialIndexQueryImpl query;
+	cpSpatialIndexSegmentQueryImpl segmentQuery;
+};
+
+/// Destroy and free a spatial index.
+CP_EXPORT void cpSpatialIndexFree(cpSpatialIndex *index);
+/// Collide the objects in @c dynamicIndex against the objects in @c staticIndex using the query callback function.
+CP_EXPORT void cpSpatialIndexCollideStatic(cpSpatialIndex *dynamicIndex, cpSpatialIndex *staticIndex, cpSpatialIndexQueryFunc func, void *data);
+
+/// Destroy a spatial index.
+static inline void cpSpatialIndexDestroy(cpSpatialIndex *index)
+{
+	if(index->klass) index->klass->destroy(index);
+}
+
+/// Get the number of objects in the spatial index.
+static inline int cpSpatialIndexCount(cpSpatialIndex *index)
+{
+	return index->klass->count(index);
+}
+
+/// Iterate the objects in the spatial index. @c func will be called once for each object.
+static inline void cpSpatialIndexEach(cpSpatialIndex *index, cpSpatialIndexIteratorFunc func, void *data)
+{
+	index->klass->each(index, func, data);
+}
+
+/// Returns true if the spatial index contains the given object.
+/// Most spatial indexes use hashed storage, so you must provide a hash value too.
+static inline cpBool cpSpatialIndexContains(cpSpatialIndex *index, void *obj, cpHashValue hashid)
+{
+	return index->klass->contains(index, obj, hashid);
+}
+
+/// Add an object to a spatial index.
+/// Most spatial indexes use hashed storage, so you must provide a hash value too.
+static inline void cpSpatialIndexInsert(cpSpatialIndex *index, void *obj, cpHashValue hashid)
+{
+	index->klass->insert(index, obj, hashid);
+}
+
+/// Remove an object from a spatial index.
+/// Most spatial indexes use hashed storage, so you must provide a hash value too.
+static inline void cpSpatialIndexRemove(cpSpatialIndex *index, void *obj, cpHashValue hashid)
+{
+	index->klass->remove(index, obj, hashid);
+}
+
+/// Perform a full reindex of a spatial index.
+static inline void cpSpatialIndexReindex(cpSpatialIndex *index)
+{
+	index->klass->reindex(index);
+}
+
+/// Reindex a single object in the spatial index.
+static inline void cpSpatialIndexReindexObject(cpSpatialIndex *index, void *obj, cpHashValue hashid)
+{
+	index->klass->reindexObject(index, obj, hashid);
+}
+
+/// Perform a rectangle query against the spatial index, calling @c func for each potential match.
+static inline void cpSpatialIndexQuery(cpSpatialIndex *index, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data)
+{
+	index->klass->query(index, obj, bb, func, data);
+}
+
+/// Perform a segment query against the spatial index, calling @c func for each potential match.
+static inline void cpSpatialIndexSegmentQuery(cpSpatialIndex *index, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data)
+{
+	index->klass->segmentQuery(index, obj, a, b, t_exit, func, data);
+}
+
+/// Simultaneously reindex and find all colliding objects.
+/// @c func will be called once for each potentially overlapping pair of objects found.
+/// If the spatial index was initialized with a static index, it will collide it's objects against that as well.
+static inline void cpSpatialIndexReindexQuery(cpSpatialIndex *index, cpSpatialIndexQueryFunc func, void *data)
+{
+	index->klass->reindexQuery(index, func, data);
+}
+
+///@}
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpTransform.h b/Chipmunk2D-7.0.2/include/chipmunk/cpTransform.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpTransform.h
@@ -0,0 +1,198 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef CHIPMUNK_TRANSFORM_H
+#define CHIPMUNK_TRANSFORM_H
+
+#include "chipmunk_types.h"
+#include "cpVect.h"
+#include "cpBB.h"
+
+/// Identity transform matrix.
+static const cpTransform cpTransformIdentity = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
+
+/// Construct a new transform matrix.
+/// (a, b) is the x basis vector.
+/// (c, d) is the y basis vector.
+/// (tx, ty) is the translation.
+static inline cpTransform
+cpTransformNew(cpFloat a, cpFloat b, cpFloat c, cpFloat d, cpFloat tx, cpFloat ty)
+{
+	cpTransform t = {a, b, c, d, tx, ty};
+	return t;
+}
+
+/// Construct a new transform matrix in transposed order.
+static inline cpTransform
+cpTransformNewTranspose(cpFloat a, cpFloat c, cpFloat tx, cpFloat b, cpFloat d, cpFloat ty)
+{
+	cpTransform t = {a, b, c, d, tx, ty};
+	return t;
+}
+
+/// Get the inverse of a transform matrix.
+static inline cpTransform
+cpTransformInverse(cpTransform t)
+{
+  cpFloat inv_det = 1.0/(t.a*t.d - t.c*t.b);
+  return cpTransformNewTranspose(
+     t.d*inv_det, -t.c*inv_det, (t.c*t.ty - t.tx*t.d)*inv_det,
+    -t.b*inv_det,  t.a*inv_det, (t.tx*t.b - t.a*t.ty)*inv_det
+  );
+}
+
+/// Multiply two transformation matrices.
+static inline cpTransform
+cpTransformMult(cpTransform t1, cpTransform t2)
+{
+  return cpTransformNewTranspose(
+    t1.a*t2.a + t1.c*t2.b, t1.a*t2.c + t1.c*t2.d, t1.a*t2.tx + t1.c*t2.ty + t1.tx,
+    t1.b*t2.a + t1.d*t2.b, t1.b*t2.c + t1.d*t2.d, t1.b*t2.tx + t1.d*t2.ty + t1.ty
+  );
+}
+
+/// Transform an absolute point. (i.e. a vertex)
+static inline cpVect
+cpTransformPoint(cpTransform t, cpVect p)
+{
+  return cpv(t.a*p.x + t.c*p.y + t.tx, t.b*p.x + t.d*p.y + t.ty);
+}
+
+/// Transform a vector (i.e. a normal)
+static inline cpVect
+cpTransformVect(cpTransform t, cpVect v)
+{
+  return cpv(t.a*v.x + t.c*v.y, t.b*v.x + t.d*v.y);
+}
+
+/// Transform a cpBB.
+static inline cpBB
+cpTransformbBB(cpTransform t, cpBB bb)
+{
+	cpVect center = cpBBCenter(bb);
+	cpFloat hw = (bb.r - bb.l)*0.5;
+	cpFloat hh = (bb.t - bb.b)*0.5;
+	
+	cpFloat a = t.a*hw, b = t.c*hh, d = t.b*hw, e = t.d*hh;
+	cpFloat hw_max = cpfmax(cpfabs(a + b), cpfabs(a - b));
+	cpFloat hh_max = cpfmax(cpfabs(d + e), cpfabs(d - e));
+	return cpBBNewForExtents(cpTransformPoint(t, center), hw_max, hh_max);
+}
+
+/// Create a transation matrix.
+static inline cpTransform
+cpTransformTranslate(cpVect translate)
+{
+  return cpTransformNewTranspose(
+    1.0, 0.0, translate.x,
+    0.0, 1.0, translate.y
+  );
+}
+
+/// Create a scale matrix.
+static inline cpTransform
+cpTransformScale(cpFloat scaleX, cpFloat scaleY)
+{
+	return cpTransformNewTranspose(
+		scaleX,    0.0, 0.0,
+		   0.0, scaleY, 0.0
+	);
+}
+
+/// Create a rotation matrix.
+static inline cpTransform
+cpTransformRotate(cpFloat radians)
+{
+	cpVect rot = cpvforangle(radians);
+	return cpTransformNewTranspose(
+		rot.x, -rot.y, 0.0,
+		rot.y,  rot.x, 0.0
+	);
+}
+
+/// Create a rigid transformation matrix. (transation + rotation)
+static inline cpTransform
+cpTransformRigid(cpVect translate, cpFloat radians)
+{
+	cpVect rot = cpvforangle(radians);
+	return cpTransformNewTranspose(
+		rot.x, -rot.y, translate.x,
+		rot.y,  rot.x, translate.y
+	);
+}
+
+/// Fast inverse of a rigid transformation matrix.
+static inline cpTransform
+cpTransformRigidInverse(cpTransform t)
+{
+  return cpTransformNewTranspose(
+     t.d, -t.c, (t.c*t.ty - t.tx*t.d),
+    -t.b,  t.a, (t.tx*t.b - t.a*t.ty)
+  );
+}
+
+//MARK: Miscellaneous (but useful) transformation matrices.
+// See source for documentation...
+
+static inline cpTransform
+cpTransformWrap(cpTransform outer, cpTransform inner)
+{
+  return cpTransformMult(cpTransformInverse(outer), cpTransformMult(inner, outer));
+}
+
+static inline cpTransform
+cpTransformWrapInverse(cpTransform outer, cpTransform inner)
+{
+  return cpTransformMult(outer, cpTransformMult(inner, cpTransformInverse(outer)));
+}
+
+static inline cpTransform
+cpTransformOrtho(cpBB bb)
+{
+  return cpTransformNewTranspose(
+    2.0/(bb.r - bb.l), 0.0, -(bb.r + bb.l)/(bb.r - bb.l),
+    0.0, 2.0/(bb.t - bb.b), -(bb.t + bb.b)/(bb.t - bb.b)
+  );
+}
+
+static inline cpTransform
+cpTransformBoneScale(cpVect v0, cpVect v1)
+{
+  cpVect d = cpvsub(v1, v0); 
+  return cpTransformNewTranspose(
+    d.x, -d.y, v0.x,
+    d.y,  d.x, v0.y
+  );
+}
+
+static inline cpTransform
+cpTransformAxialScale(cpVect axis, cpVect pivot, cpFloat scale)
+{
+  cpFloat A = axis.x*axis.y*(scale - 1.0);
+  cpFloat B = cpvdot(axis, pivot)*(1.0 - scale);
+  
+  return cpTransformNewTranspose(
+    scale*axis.x*axis.x + axis.y*axis.y, A, axis.x*B,
+    A, axis.x*axis.x + scale*axis.y*axis.y, axis.y*B
+  );
+}
+
+#endif
diff --git a/Chipmunk2D-7.0.2/include/chipmunk/cpVect.h b/Chipmunk2D-7.0.2/include/chipmunk/cpVect.h
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/include/chipmunk/cpVect.h
@@ -0,0 +1,230 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef CHIPMUNK_VECT_H
+#define CHIPMUNK_VECT_H
+
+#include "chipmunk_types.h"
+
+/// @defgroup cpVect cpVect
+/// Chipmunk's 2D vector type along with a handy 2D vector math lib.
+/// @{
+
+/// Constant for the zero vector.
+static const cpVect cpvzero = {0.0f,0.0f};
+
+/// Convenience constructor for cpVect structs.
+static inline cpVect cpv(const cpFloat x, const cpFloat y)
+{
+	cpVect v = {x, y};
+	return v;
+}
+
+/// Check if two vectors are equal. (Be careful when comparing floating point numbers!)
+static inline cpBool cpveql(const cpVect v1, const cpVect v2)
+{
+	return (v1.x == v2.x && v1.y == v2.y);
+}
+
+/// Add two vectors
+static inline cpVect cpvadd(const cpVect v1, const cpVect v2)
+{
+	return cpv(v1.x + v2.x, v1.y + v2.y);
+}
+
+/// Subtract two vectors.
+static inline cpVect cpvsub(const cpVect v1, const cpVect v2)
+{
+	return cpv(v1.x - v2.x, v1.y - v2.y);
+}
+
+/// Negate a vector.
+static inline cpVect cpvneg(const cpVect v)
+{
+	return cpv(-v.x, -v.y);
+}
+
+/// Scalar multiplication.
+static inline cpVect cpvmult(const cpVect v, const cpFloat s)
+{
+	return cpv(v.x*s, v.y*s);
+}
+
+/// Vector dot product.
+static inline cpFloat cpvdot(const cpVect v1, const cpVect v2)
+{
+	return v1.x*v2.x + v1.y*v2.y;
+}
+
+/// 2D vector cross product analog.
+/// The cross product of 2D vectors results in a 3D vector with only a z component.
+/// This function returns the magnitude of the z value.
+static inline cpFloat cpvcross(const cpVect v1, const cpVect v2)
+{
+	return v1.x*v2.y - v1.y*v2.x;
+}
+
+/// Returns a perpendicular vector. (90 degree rotation)
+static inline cpVect cpvperp(const cpVect v)
+{
+	return cpv(-v.y, v.x);
+}
+
+/// Returns a perpendicular vector. (-90 degree rotation)
+static inline cpVect cpvrperp(const cpVect v)
+{
+	return cpv(v.y, -v.x);
+}
+
+/// Returns the vector projection of v1 onto v2.
+static inline cpVect cpvproject(const cpVect v1, const cpVect v2)
+{
+	return cpvmult(v2, cpvdot(v1, v2)/cpvdot(v2, v2));
+}
+
+/// Returns the unit length vector for the given angle (in radians).
+static inline cpVect cpvforangle(const cpFloat a)
+{
+	return cpv(cpfcos(a), cpfsin(a));
+}
+
+/// Returns the angular direction v is pointing in (in radians).
+static inline cpFloat cpvtoangle(const cpVect v)
+{
+	return cpfatan2(v.y, v.x);
+}
+
+/// Uses complex number multiplication to rotate v1 by v2. Scaling will occur if v1 is not a unit vector.
+static inline cpVect cpvrotate(const cpVect v1, const cpVect v2)
+{
+	return cpv(v1.x*v2.x - v1.y*v2.y, v1.x*v2.y + v1.y*v2.x);
+}
+
+/// Inverse of cpvrotate().
+static inline cpVect cpvunrotate(const cpVect v1, const cpVect v2)
+{
+	return cpv(v1.x*v2.x + v1.y*v2.y, v1.y*v2.x - v1.x*v2.y);
+}
+
+/// Returns the squared length of v. Faster than cpvlength() when you only need to compare lengths.
+static inline cpFloat cpvlengthsq(const cpVect v)
+{
+	return cpvdot(v, v);
+}
+
+/// Returns the length of v.
+static inline cpFloat cpvlength(const cpVect v)
+{
+	return cpfsqrt(cpvdot(v, v));
+}
+
+/// Linearly interpolate between v1 and v2.
+static inline cpVect cpvlerp(const cpVect v1, const cpVect v2, const cpFloat t)
+{
+	return cpvadd(cpvmult(v1, 1.0f - t), cpvmult(v2, t));
+}
+
+/// Returns a normalized copy of v.
+static inline cpVect cpvnormalize(const cpVect v)
+{
+	// Neat trick I saw somewhere to avoid div/0.
+	return cpvmult(v, 1.0f/(cpvlength(v) + CPFLOAT_MIN));
+}
+
+/// Spherical linearly interpolate between v1 and v2.
+static inline cpVect
+cpvslerp(const cpVect v1, const cpVect v2, const cpFloat t)
+{
+	cpFloat dot = cpvdot(cpvnormalize(v1), cpvnormalize(v2));
+	cpFloat omega = cpfacos(cpfclamp(dot, -1.0f, 1.0f));
+	
+	if(omega < 1e-3){
+		// If the angle between two vectors is very small, lerp instead to avoid precision issues.
+		return cpvlerp(v1, v2, t);
+	} else {
+		cpFloat denom = 1.0f/cpfsin(omega);
+		return cpvadd(cpvmult(v1, cpfsin((1.0f - t)*omega)*denom), cpvmult(v2, cpfsin(t*omega)*denom));
+	}
+}
+
+/// Spherical linearly interpolate between v1 towards v2 by no more than angle a radians
+static inline cpVect
+cpvslerpconst(const cpVect v1, const cpVect v2, const cpFloat a)
+{
+	cpFloat dot = cpvdot(cpvnormalize(v1), cpvnormalize(v2));
+	cpFloat omega = cpfacos(cpfclamp(dot, -1.0f, 1.0f));
+	
+	return cpvslerp(v1, v2, cpfmin(a, omega)/omega);
+}
+
+/// Clamp v to length len.
+static inline cpVect cpvclamp(const cpVect v, const cpFloat len)
+{
+	return (cpvdot(v,v) > len*len) ? cpvmult(cpvnormalize(v), len) : v;
+}
+
+/// Linearly interpolate between v1 towards v2 by distance d.
+static inline cpVect cpvlerpconst(cpVect v1, cpVect v2, cpFloat d)
+{
+	return cpvadd(v1, cpvclamp(cpvsub(v2, v1), d));
+}
+
+/// Returns the distance between v1 and v2.
+static inline cpFloat cpvdist(const cpVect v1, const cpVect v2)
+{
+	return cpvlength(cpvsub(v1, v2));
+}
+
+/// Returns the squared distance between v1 and v2. Faster than cpvdist() when you only need to compare distances.
+static inline cpFloat cpvdistsq(const cpVect v1, const cpVect v2)
+{
+	return cpvlengthsq(cpvsub(v1, v2));
+}
+
+/// Returns true if the distance between v1 and v2 is less than dist.
+static inline cpBool cpvnear(const cpVect v1, const cpVect v2, const cpFloat dist)
+{
+	return cpvdistsq(v1, v2) < dist*dist;
+}
+
+/// @}
+
+/// @defgroup cpMat2x2 cpMat2x2
+/// 2x2 matrix type used for tensors and such.
+/// @{
+
+// NUKE
+static inline cpMat2x2
+cpMat2x2New(cpFloat a, cpFloat b, cpFloat c, cpFloat d)
+{
+	cpMat2x2 m = {a, b, c, d};
+	return m;
+}
+
+static inline cpVect
+cpMat2x2Transform(cpMat2x2 m, cpVect v)
+{
+	return cpv(v.x*m.a + v.y*m.b, v.x*m.c + v.y*m.d);
+}
+
+///@}
+
+#endif
diff --git a/Chipmunk2D-7.0.2/src/chipmunk.c b/Chipmunk2D-7.0.2/src/chipmunk.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/chipmunk.c
@@ -0,0 +1,331 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#if defined(ANDROID)
+#	include <android/log.h>
+#endif
+
+#include "chipmunk/chipmunk_private.h"
+
+void
+cpMessage(const char *condition, const char *file, int line, int isError, int isHardError, const char *message, ...)
+{
+	fprintf(stderr, (isError ? "Aborting due to Chipmunk error: " : "Chipmunk warning: "));
+	
+	va_list vargs;
+	va_start(vargs, message); {
+#if defined(ANDROID)
+		__android_log_print( ANDROID_LOG_INFO, "Chipmunk", "%s(%d)", file, line );
+		__android_log_print( ANDROID_LOG_INFO, "Chipmunk", message, vargs );
+#else
+		vfprintf(stderr, message, vargs);
+		fprintf(stderr, "\n");
+#endif
+	} va_end(vargs);
+	
+#if defined(ANDROID)
+	__android_log_print(ANDROID_LOG_INFO, "Chipmunk", "\tFailed condition: %s\n", condition);
+	__android_log_print(ANDROID_LOG_INFO, "Chipmunk", "\tSource:%s:%d\n", file, line);
+#else
+	fprintf(stderr, "\tFailed condition: %s\n", condition);
+	fprintf(stderr, "\tSource:%s:%d\n", file, line);
+#endif
+}
+
+#define STR(s) #s
+#define XSTR(s) STR(s)
+
+const char *cpVersionString = XSTR(CP_VERSION_MAJOR) "." XSTR(CP_VERSION_MINOR) "." XSTR(CP_VERSION_RELEASE);
+
+//MARK: Misc Functions
+
+cpFloat
+cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset)
+{
+	return m*(0.5f*(r1*r1 + r2*r2) + cpvlengthsq(offset));
+}
+
+cpFloat
+cpAreaForCircle(cpFloat r1, cpFloat r2)
+{
+	return (cpFloat)CP_PI*cpfabs(r1*r1 - r2*r2);
+}
+
+cpFloat
+cpMomentForSegment(cpFloat m, cpVect a, cpVect b, cpFloat r)
+{
+	cpVect offset = cpvlerp(a, b, 0.5f);
+	
+	// This approximates the shape as a box for rounded segments, but it's quite close.
+	cpFloat length = cpvdist(b, a) + 2.0f*r;
+	return m*((length*length + 4.0f*r*r)/12.0f + cpvlengthsq(offset));
+}
+
+cpFloat
+cpAreaForSegment(cpVect a, cpVect b, cpFloat r)
+{
+	return r*((cpFloat)CP_PI*r + 2.0f*cpvdist(a, b));
+}
+
+cpFloat
+cpMomentForPoly(cpFloat m, const int count, const cpVect *verts, cpVect offset, cpFloat r)
+{
+	// TODO account for radius.
+	if(count == 2) return cpMomentForSegment(m, verts[0], verts[1], 0.0f);
+	
+	cpFloat sum1 = 0.0f;
+	cpFloat sum2 = 0.0f;
+	for(int i=0; i<count; i++){
+		cpVect v1 = cpvadd(verts[i], offset);
+		cpVect v2 = cpvadd(verts[(i+1)%count], offset);
+		
+		cpFloat a = cpvcross(v2, v1);
+		cpFloat b = cpvdot(v1, v1) + cpvdot(v1, v2) + cpvdot(v2, v2);
+		
+		sum1 += a*b;
+		sum2 += a;
+	}
+	
+	return (m*sum1)/(6.0f*sum2);
+}
+
+cpFloat
+cpAreaForPoly(const int count, const cpVect *verts, cpFloat r)
+{
+	cpFloat area = 0.0f;
+	cpFloat perimeter = 0.0f;
+	for(int i=0; i<count; i++){
+		cpVect v1 = verts[i];
+		cpVect v2 = verts[(i+1)%count];
+		
+		area += cpvcross(v1, v2);
+		perimeter += cpvdist(v1, v2);
+	}
+	
+	return r*(CP_PI*cpfabs(r) + perimeter) + area/2.0f;
+}
+
+cpVect
+cpCentroidForPoly(const int count, const cpVect *verts)
+{
+	cpFloat sum = 0.0f;
+	cpVect vsum = cpvzero;
+	
+	for(int i=0; i<count; i++){
+		cpVect v1 = verts[i];
+		cpVect v2 = verts[(i+1)%count];
+		cpFloat cross = cpvcross(v1, v2);
+		
+		sum += cross;
+		vsum = cpvadd(vsum, cpvmult(cpvadd(v1, v2), cross));
+	}
+	
+	return cpvmult(vsum, 1.0f/(3.0f*sum));
+}
+
+//void
+//cpRecenterPoly(const int count, cpVect *verts){
+//	cpVect centroid = cpCentroidForPoly(count, verts);
+//	
+//	for(int i=0; i<count; i++){
+//		verts[i] = cpvsub(verts[i], centroid);
+//	}
+//}
+
+cpFloat
+cpMomentForBox(cpFloat m, cpFloat width, cpFloat height)
+{
+	return m*(width*width + height*height)/12.0f;
+}
+
+cpFloat
+cpMomentForBox2(cpFloat m, cpBB box)
+{
+	cpFloat width = box.r - box.l;
+	cpFloat height = box.t - box.b;
+	cpVect offset = cpvmult(cpv(box.l + box.r, box.b + box.t), 0.5f);
+	
+	// TODO: NaN when offset is 0 and m is INFINITY
+	return cpMomentForBox(m, width, height) + m*cpvlengthsq(offset);
+}
+
+//MARK: Quick Hull
+
+void
+cpLoopIndexes(const cpVect *verts, int count, int *start, int *end)
+{
+	(*start) = (*end) = 0;
+	cpVect min = verts[0];
+	cpVect max = min;
+	
+  for(int i=1; i<count; i++){
+    cpVect v = verts[i];
+		
+    if(v.x < min.x || (v.x == min.x && v.y < min.y)){
+      min = v;
+      (*start) = i;
+    } else if(v.x > max.x || (v.x == max.x && v.y > max.y)){
+			max = v;
+			(*end) = i;
+		}
+	}
+}
+
+#define SWAP(__A__, __B__) {cpVect __TMP__ = __A__; __A__ = __B__; __B__ = __TMP__;}
+
+static int
+QHullPartition(cpVect *verts, int count, cpVect a, cpVect b, cpFloat tol)
+{
+	if(count == 0) return 0;
+	
+	cpFloat max = 0;
+	int pivot = 0;
+	
+	cpVect delta = cpvsub(b, a);
+	cpFloat valueTol = tol*cpvlength(delta);
+	
+	int head = 0;
+	for(int tail = count-1; head <= tail;){
+		cpFloat value = cpvcross(cpvsub(verts[head], a), delta);
+		if(value > valueTol){
+			if(value > max){
+				max = value;
+				pivot = head;
+			}
+			
+			head++;
+		} else {
+			SWAP(verts[head], verts[tail]);
+			tail--;
+		}
+	}
+	
+	// move the new pivot to the front if it's not already there.
+	if(pivot != 0) SWAP(verts[0], verts[pivot]);
+	return head;
+}
+
+static int
+QHullReduce(cpFloat tol, cpVect *verts, int count, cpVect a, cpVect pivot, cpVect b, cpVect *result)
+{
+	if(count < 0){
+		return 0;
+	} else if(count == 0) {
+		result[0] = pivot;
+		return 1;
+	} else {
+		int left_count = QHullPartition(verts, count, a, pivot, tol);
+		int index = QHullReduce(tol, verts + 1, left_count - 1, a, verts[0], pivot, result);
+		
+		result[index++] = pivot;
+		
+		int right_count = QHullPartition(verts + left_count, count - left_count, pivot, b, tol);
+		return index + QHullReduce(tol, verts + left_count + 1, right_count - 1, pivot, verts[left_count], b, result + index);
+	}
+}
+
+// QuickHull seemed like a neat algorithm, and efficient-ish for large input sets.
+// My implementation performs an in place reduction using the result array as scratch space.
+int
+cpConvexHull(int count, const cpVect *verts, cpVect *result, int *first, cpFloat tol)
+{
+	if(verts != result){
+		// Copy the line vertexes into the empty part of the result polyline to use as a scratch buffer.
+		memcpy(result, verts, count*sizeof(cpVect));
+	}
+	
+	// Degenerate case, all points are the same.
+	int start, end;
+	cpLoopIndexes(verts, count, &start, &end);
+	if(start == end){
+		if(first) (*first) = 0;
+		return 1;
+	}
+	
+	SWAP(result[0], result[start]);
+	SWAP(result[1], result[end == 0 ? start : end]);
+	
+	cpVect a = result[0];
+	cpVect b = result[1];
+	
+	if(first) (*first) = start;
+	return QHullReduce(tol, result + 2, count - 2, a, b, a, result + 1) + 1;
+}
+
+//MARK: Alternate Block Iterators
+
+#if defined(__has_extension)
+#if __has_extension(blocks)
+
+static void IteratorFunc(void *ptr, void (^block)(void *ptr)){block(ptr);}
+
+void cpSpaceEachBody_b(cpSpace *space, void (^block)(cpBody *body)){
+	cpSpaceEachBody(space, (cpSpaceBodyIteratorFunc)IteratorFunc, block);
+}
+
+void cpSpaceEachShape_b(cpSpace *space, void (^block)(cpShape *shape)){
+	cpSpaceEachShape(space, (cpSpaceShapeIteratorFunc)IteratorFunc, block);
+}
+
+void cpSpaceEachConstraint_b(cpSpace *space, void (^block)(cpConstraint *constraint)){
+	cpSpaceEachConstraint(space, (cpSpaceConstraintIteratorFunc)IteratorFunc, block);
+}
+
+static void BodyIteratorFunc(cpBody *body, void *ptr, void (^block)(void *ptr)){block(ptr);}
+
+void cpBodyEachShape_b(cpBody *body, void (^block)(cpShape *shape)){
+	cpBodyEachShape(body, (cpBodyShapeIteratorFunc)BodyIteratorFunc, block);
+}
+
+void cpBodyEachConstraint_b(cpBody *body, void (^block)(cpConstraint *constraint)){
+	cpBodyEachConstraint(body, (cpBodyConstraintIteratorFunc)BodyIteratorFunc, block);
+}
+
+void cpBodyEachArbiter_b(cpBody *body, void (^block)(cpArbiter *arbiter)){
+	cpBodyEachArbiter(body, (cpBodyArbiterIteratorFunc)BodyIteratorFunc, block);
+}
+
+static void PointQueryIteratorFunc(cpShape *shape, cpVect p, cpFloat d, cpVect g, cpSpacePointQueryBlock block){block(shape, p, d, g);}
+void cpSpacePointQuery_b(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpSpacePointQueryBlock block){
+	cpSpacePointQuery(space, point, maxDistance, filter, (cpSpacePointQueryFunc)PointQueryIteratorFunc, block);
+}
+
+static void SegmentQueryIteratorFunc(cpShape *shape, cpVect p, cpVect n, cpFloat t, cpSpaceSegmentQueryBlock block){block(shape, p, n, t);}
+void cpSpaceSegmentQuery_b(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSpaceSegmentQueryBlock block){
+	cpSpaceSegmentQuery(space, start, end, radius, filter, (cpSpaceSegmentQueryFunc)SegmentQueryIteratorFunc, block);
+}
+
+void cpSpaceBBQuery_b(cpSpace *space, cpBB bb, cpShapeFilter filter, cpSpaceBBQueryBlock block){
+	cpSpaceBBQuery(space, bb, filter, (cpSpaceBBQueryFunc)IteratorFunc, block);
+}
+
+static void ShapeQueryIteratorFunc(cpShape *shape, cpContactPointSet *points, cpSpaceShapeQueryBlock block){block(shape, points);}
+cpBool cpSpaceShapeQuery_b(cpSpace *space, cpShape *shape, cpSpaceShapeQueryBlock block){
+	return cpSpaceShapeQuery(space, shape, (cpSpaceShapeQueryFunc)ShapeQueryIteratorFunc, block);
+}
+
+#endif
+#endif
+
+#include "chipmunk/chipmunk_ffi.h"
diff --git a/Chipmunk2D-7.0.2/src/cpArbiter.c b/Chipmunk2D-7.0.2/src/cpArbiter.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpArbiter.c
@@ -0,0 +1,496 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+// TODO: make this generic so I can reuse it for constraints also.
+static inline void
+unthreadHelper(cpArbiter *arb, cpBody *body)
+{
+	struct cpArbiterThread *thread = cpArbiterThreadForBody(arb, body);
+	cpArbiter *prev = thread->prev;
+	cpArbiter *next = thread->next;
+	
+	if(prev){
+		cpArbiterThreadForBody(prev, body)->next = next;
+	} else if(body->arbiterList == arb) {
+		// IFF prev is NULL and body->arbiterList == arb, is arb at the head of the list.
+		// This function may be called for an arbiter that was never in a list.
+		// In that case, we need to protect it from wiping out the body->arbiterList pointer.
+		body->arbiterList = next;
+	}
+	
+	if(next) cpArbiterThreadForBody(next, body)->prev = prev;
+	
+	thread->prev = NULL;
+	thread->next = NULL;
+}
+
+void
+cpArbiterUnthread(cpArbiter *arb)
+{
+	unthreadHelper(arb, arb->body_a);
+	unthreadHelper(arb, arb->body_b);
+}
+
+cpBool cpArbiterIsFirstContact(const cpArbiter *arb)
+{
+	return arb->state == CP_ARBITER_STATE_FIRST_COLLISION;
+}
+
+cpBool cpArbiterIsRemoval(const cpArbiter *arb)
+{
+	return arb->state == CP_ARBITER_STATE_INVALIDATED;
+}
+
+int cpArbiterGetCount(const cpArbiter *arb)
+{
+	// Return 0 contacts if we are in a separate callback.
+	return (arb->state < CP_ARBITER_STATE_CACHED ? arb->count : 0);
+}
+
+cpVect
+cpArbiterGetNormal(const cpArbiter *arb)
+{
+	return cpvmult(arb->n, arb->swapped ? -1.0f : 1.0);
+}
+
+cpVect
+cpArbiterGetPointA(const cpArbiter *arb, int i)
+{
+	cpAssertHard(0 <= i && i < cpArbiterGetCount(arb), "Index error: The specified contact index is invalid for this arbiter");
+	return cpvadd(arb->body_a->p, arb->contacts[i].r1);
+}
+
+cpVect
+cpArbiterGetPointB(const cpArbiter *arb, int i)
+{
+	cpAssertHard(0 <= i && i < cpArbiterGetCount(arb), "Index error: The specified contact index is invalid for this arbiter");
+	return cpvadd(arb->body_b->p, arb->contacts[i].r2);
+}
+
+cpFloat
+cpArbiterGetDepth(const cpArbiter *arb, int i)
+{
+	cpAssertHard(0 <= i && i < cpArbiterGetCount(arb), "Index error: The specified contact index is invalid for this arbiter");
+	
+	struct cpContact *con = &arb->contacts[i];
+	return cpvdot(cpvadd(cpvsub(con->r2, con->r1), cpvsub(arb->body_b->p, arb->body_a->p)), arb->n);
+}
+
+cpContactPointSet
+cpArbiterGetContactPointSet(const cpArbiter *arb)
+{
+	cpContactPointSet set;
+	set.count = cpArbiterGetCount(arb);
+	
+	cpBool swapped = arb->swapped;
+	cpVect n = arb->n;
+	set.normal = (swapped ? cpvneg(n) : n);
+	
+	for(int i=0; i<set.count; i++){
+		// Contact points are relative to body CoGs;
+		cpVect p1 = cpvadd(arb->body_a->p, arb->contacts[i].r1);
+		cpVect p2 = cpvadd(arb->body_b->p, arb->contacts[i].r2);
+		
+		set.points[i].pointA = (swapped ? p2 : p1);
+		set.points[i].pointB = (swapped ? p1 : p2);
+		set.points[i].distance = cpvdot(cpvsub(p2, p1), n);
+	}
+	
+	return set;
+}
+
+void
+cpArbiterSetContactPointSet(cpArbiter *arb, cpContactPointSet *set)
+{
+	int count = set->count;
+	cpAssertHard(count == arb->count, "The number of contact points cannot be changed.");
+	
+	cpBool swapped = arb->swapped;
+	arb->n = (swapped ? cpvneg(set->normal) : set->normal);
+	
+	for(int i=0; i<count; i++){
+		// Convert back to CoG relative offsets.
+		cpVect p1 = set->points[i].pointA;
+		cpVect p2 = set->points[i].pointB;
+		
+		arb->contacts[i].r1 = cpvsub(swapped ? p2 : p1, arb->body_a->p);
+		arb->contacts[i].r2 = cpvsub(swapped ? p1 : p2, arb->body_b->p);
+	}
+}
+
+cpVect
+cpArbiterTotalImpulse(const cpArbiter *arb)
+{
+	struct cpContact *contacts = arb->contacts;
+	cpVect n = arb->n;
+	cpVect sum = cpvzero;
+	
+	for(int i=0, count=cpArbiterGetCount(arb); i<count; i++){
+		struct cpContact *con = &contacts[i];
+		sum = cpvadd(sum, cpvrotate(n, cpv(con->jnAcc, con->jtAcc)));
+	}
+		
+	return (arb->swapped ? sum : cpvneg(sum));
+	return cpvzero;
+}
+
+cpFloat
+cpArbiterTotalKE(const cpArbiter *arb)
+{
+	cpFloat eCoef = (1 - arb->e)/(1 + arb->e);
+	cpFloat sum = 0.0;
+	
+	struct cpContact *contacts = arb->contacts;
+	for(int i=0, count=cpArbiterGetCount(arb); i<count; i++){
+		struct cpContact *con = &contacts[i];
+		cpFloat jnAcc = con->jnAcc;
+		cpFloat jtAcc = con->jtAcc;
+		
+		sum += eCoef*jnAcc*jnAcc/con->nMass + jtAcc*jtAcc/con->tMass;
+	}
+	
+	return sum;
+}
+
+cpBool
+cpArbiterIgnore(cpArbiter *arb)
+{
+	arb->state = CP_ARBITER_STATE_IGNORE;
+	return cpFalse;
+}
+
+cpFloat
+cpArbiterGetRestitution(const cpArbiter *arb)
+{
+	return arb->e;
+}
+
+void
+cpArbiterSetRestitution(cpArbiter *arb, cpFloat restitution)
+{
+	arb->e = restitution;
+}
+
+cpFloat
+cpArbiterGetFriction(const cpArbiter *arb)
+{
+	return arb->u;
+}
+
+void
+cpArbiterSetFriction(cpArbiter *arb, cpFloat friction)
+{
+	arb->u = friction;
+}
+
+cpVect
+cpArbiterGetSurfaceVelocity(cpArbiter *arb)
+{
+	return cpvmult(arb->surface_vr, arb->swapped ? -1.0f : 1.0);
+}
+
+void
+cpArbiterSetSurfaceVelocity(cpArbiter *arb, cpVect vr)
+{
+	arb->surface_vr = cpvmult(vr, arb->swapped ? -1.0f : 1.0);
+}
+
+cpDataPointer
+cpArbiterGetUserData(const cpArbiter *arb)
+{
+	return arb->data;
+}
+
+void
+cpArbiterSetUserData(cpArbiter *arb, cpDataPointer userData)
+{
+	arb->data = userData;
+}
+
+void
+cpArbiterGetShapes(const cpArbiter *arb, cpShape **a, cpShape **b)
+{
+	if(arb->swapped){
+		(*a) = (cpShape *)arb->b, (*b) = (cpShape *)arb->a;
+	} else {
+		(*a) = (cpShape *)arb->a, (*b) = (cpShape *)arb->b;
+	}
+}
+
+void cpArbiterGetBodies(const cpArbiter *arb, cpBody **a, cpBody **b)
+{
+	CP_ARBITER_GET_SHAPES(arb, shape_a, shape_b);
+	(*a) = shape_a->body;
+	(*b) = shape_b->body;
+}
+
+cpBool
+cpArbiterCallWildcardBeginA(cpArbiter *arb, cpSpace *space)
+{
+	cpCollisionHandler *handler = arb->handlerA;
+	return handler->beginFunc(arb, space, handler->userData);
+}
+
+cpBool
+cpArbiterCallWildcardBeginB(cpArbiter *arb, cpSpace *space)
+{
+	cpCollisionHandler *handler = arb->handlerB;
+	arb->swapped = !arb->swapped;
+	cpBool retval = handler->beginFunc(arb, space, handler->userData);
+	arb->swapped = !arb->swapped;
+	return retval;
+}
+
+cpBool
+cpArbiterCallWildcardPreSolveA(cpArbiter *arb, cpSpace *space)
+{
+	cpCollisionHandler *handler = arb->handlerA;
+	return handler->preSolveFunc(arb, space, handler->userData);
+}
+
+cpBool
+cpArbiterCallWildcardPreSolveB(cpArbiter *arb, cpSpace *space)
+{
+	cpCollisionHandler *handler = arb->handlerB;
+	arb->swapped = !arb->swapped;
+	cpBool retval = handler->preSolveFunc(arb, space, handler->userData);
+	arb->swapped = !arb->swapped;
+	return retval;
+}
+
+void
+cpArbiterCallWildcardPostSolveA(cpArbiter *arb, cpSpace *space)
+{
+	cpCollisionHandler *handler = arb->handlerA;
+	handler->postSolveFunc(arb, space, handler->userData);
+}
+
+void
+cpArbiterCallWildcardPostSolveB(cpArbiter *arb, cpSpace *space)
+{
+	cpCollisionHandler *handler = arb->handlerB;
+	arb->swapped = !arb->swapped;
+	handler->postSolveFunc(arb, space, handler->userData);
+	arb->swapped = !arb->swapped;
+}
+
+void
+cpArbiterCallWildcardSeparateA(cpArbiter *arb, cpSpace *space)
+{
+	cpCollisionHandler *handler = arb->handlerA;
+	handler->separateFunc(arb, space, handler->userData);
+}
+
+void
+cpArbiterCallWildcardSeparateB(cpArbiter *arb, cpSpace *space)
+{
+	cpCollisionHandler *handler = arb->handlerB;
+	arb->swapped = !arb->swapped;
+	handler->separateFunc(arb, space, handler->userData);
+	arb->swapped = !arb->swapped;
+}
+
+cpArbiter*
+cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b)
+{
+	arb->handler = NULL;
+	arb->swapped = cpFalse;
+	
+	arb->handler = NULL;
+	arb->handlerA = NULL;
+	arb->handlerB = NULL;
+	
+	arb->e = 0.0f;
+	arb->u = 0.0f;
+	arb->surface_vr = cpvzero;
+	
+	arb->count = 0;
+	arb->contacts = NULL;
+	
+	arb->a = a; arb->body_a = a->body;
+	arb->b = b; arb->body_b = b->body;
+	
+	arb->thread_a.next = NULL;
+	arb->thread_b.next = NULL;
+	arb->thread_a.prev = NULL;
+	arb->thread_b.prev = NULL;
+	
+	arb->stamp = 0;
+	arb->state = CP_ARBITER_STATE_FIRST_COLLISION;
+	
+	arb->data = NULL;
+	
+	return arb;
+}
+
+static inline cpCollisionHandler *
+cpSpaceLookupHandler(cpSpace *space, cpCollisionType a, cpCollisionType b, cpCollisionHandler *defaultValue)
+{
+	cpCollisionType types[] = {a, b};
+	cpCollisionHandler *handler = (cpCollisionHandler *)cpHashSetFind(space->collisionHandlers, CP_HASH_PAIR(a, b), types);
+	return (handler ? handler : defaultValue);
+}
+
+void
+cpArbiterUpdate(cpArbiter *arb, struct cpCollisionInfo *info, cpSpace *space)
+{
+	const cpShape *a = info->a, *b = info->b;
+	
+	// For collisions between two similar primitive types, the order could have been swapped since the last frame.
+	arb->a = a; arb->body_a = a->body;
+	arb->b = b; arb->body_b = b->body;
+	
+	// Iterate over the possible pairs to look for hash value matches.
+	for(int i=0; i<info->count; i++){
+		struct cpContact *con = &info->arr[i];
+		
+		// r1 and r2 store absolute offsets at init time.
+		// Need to convert them to relative offsets.
+		con->r1 = cpvsub(con->r1, a->body->p);
+		con->r2 = cpvsub(con->r2, b->body->p);
+		
+		// Cached impulses are not zeroed at init time.
+		con->jnAcc = con->jtAcc = 0.0f;
+		
+		for(int j=0; j<arb->count; j++){
+			struct cpContact *old = &arb->contacts[j];
+			
+			// This could trigger false positives, but is fairly unlikely nor serious if it does.
+			if(con->hash == old->hash){
+				// Copy the persistant contact information.
+				con->jnAcc = old->jnAcc;
+				con->jtAcc = old->jtAcc;
+			}
+		}
+	}
+	
+	arb->contacts = info->arr;
+	arb->count = info->count;
+	arb->n = info->n;
+	
+	arb->e = a->e * b->e;
+	arb->u = a->u * b->u;
+	
+	cpVect surface_vr = cpvsub(b->surfaceV, a->surfaceV);
+	arb->surface_vr = cpvsub(surface_vr, cpvmult(info->n, cpvdot(surface_vr, info->n)));
+	
+	cpCollisionType typeA = info->a->type, typeB = info->b->type;
+	cpCollisionHandler *defaultHandler = &space->defaultHandler;
+	cpCollisionHandler *handler = arb->handler = cpSpaceLookupHandler(space, typeA, typeB, defaultHandler);
+	
+	// Check if the types match, but don't swap for a default handler which use the wildcard for type A.
+	cpBool swapped = arb->swapped = (typeA != handler->typeA && handler->typeA != CP_WILDCARD_COLLISION_TYPE);
+	
+	if(handler != defaultHandler || space->usesWildcards){
+		// The order of the main handler swaps the wildcard handlers too. Uffda.
+		arb->handlerA = cpSpaceLookupHandler(space, (swapped ? typeB : typeA), CP_WILDCARD_COLLISION_TYPE, &cpCollisionHandlerDoNothing);
+		arb->handlerB = cpSpaceLookupHandler(space, (swapped ? typeA : typeB), CP_WILDCARD_COLLISION_TYPE, &cpCollisionHandlerDoNothing);
+	}
+		
+	// mark it as new if it's been cached
+	if(arb->state == CP_ARBITER_STATE_CACHED) arb->state = CP_ARBITER_STATE_FIRST_COLLISION;
+}
+
+void
+cpArbiterPreStep(cpArbiter *arb, cpFloat dt, cpFloat slop, cpFloat bias)
+{
+	cpBody *a = arb->body_a;
+	cpBody *b = arb->body_b;
+	cpVect n = arb->n;
+	cpVect body_delta = cpvsub(b->p, a->p);
+	
+	for(int i=0; i<arb->count; i++){
+		struct cpContact *con = &arb->contacts[i];
+		
+		// Calculate the mass normal and mass tangent.
+		con->nMass = 1.0f/k_scalar(a, b, con->r1, con->r2, n);
+		con->tMass = 1.0f/k_scalar(a, b, con->r1, con->r2, cpvperp(n));
+				
+		// Calculate the target bias velocity.
+		cpFloat dist = cpvdot(cpvadd(cpvsub(con->r2, con->r1), body_delta), n);
+		con->bias = -bias*cpfmin(0.0f, dist + slop)/dt;
+		con->jBias = 0.0f;
+		
+		// Calculate the target bounce velocity.
+		con->bounce = normal_relative_velocity(a, b, con->r1, con->r2, n)*arb->e;
+	}
+}
+
+void
+cpArbiterApplyCachedImpulse(cpArbiter *arb, cpFloat dt_coef)
+{
+	if(cpArbiterIsFirstContact(arb)) return;
+	
+	cpBody *a = arb->body_a;
+	cpBody *b = arb->body_b;
+	cpVect n = arb->n;
+	
+	for(int i=0; i<arb->count; i++){
+		struct cpContact *con = &arb->contacts[i];
+		cpVect j = cpvrotate(n, cpv(con->jnAcc, con->jtAcc));
+		apply_impulses(a, b, con->r1, con->r2, cpvmult(j, dt_coef));
+	}
+}
+
+// TODO: is it worth splitting velocity/position correction?
+
+void
+cpArbiterApplyImpulse(cpArbiter *arb)
+{
+	cpBody *a = arb->body_a;
+	cpBody *b = arb->body_b;
+	cpVect n = arb->n;
+	cpVect surface_vr = arb->surface_vr;
+	cpFloat friction = arb->u;
+
+	for(int i=0; i<arb->count; i++){
+		struct cpContact *con = &arb->contacts[i];
+		cpFloat nMass = con->nMass;
+		cpVect r1 = con->r1;
+		cpVect r2 = con->r2;
+		
+		cpVect vb1 = cpvadd(a->v_bias, cpvmult(cpvperp(r1), a->w_bias));
+		cpVect vb2 = cpvadd(b->v_bias, cpvmult(cpvperp(r2), b->w_bias));
+		cpVect vr = cpvadd(relative_velocity(a, b, r1, r2), surface_vr);
+		
+		cpFloat vbn = cpvdot(cpvsub(vb2, vb1), n);
+		cpFloat vrn = cpvdot(vr, n);
+		cpFloat vrt = cpvdot(vr, cpvperp(n));
+		
+		cpFloat jbn = (con->bias - vbn)*nMass;
+		cpFloat jbnOld = con->jBias;
+		con->jBias = cpfmax(jbnOld + jbn, 0.0f);
+		
+		cpFloat jn = -(con->bounce + vrn)*nMass;
+		cpFloat jnOld = con->jnAcc;
+		con->jnAcc = cpfmax(jnOld + jn, 0.0f);
+		
+		cpFloat jtMax = friction*con->jnAcc;
+		cpFloat jt = -vrt*con->tMass;
+		cpFloat jtOld = con->jtAcc;
+		con->jtAcc = cpfclamp(jtOld + jt, -jtMax, jtMax);
+		
+		apply_bias_impulses(a, b, r1, r2, cpvmult(n, con->jBias - jbnOld));
+		apply_impulses(a, b, r1, r2, cpvrotate(n, cpv(con->jnAcc - jnOld, con->jtAcc - jtOld)));
+	}
+}
diff --git a/Chipmunk2D-7.0.2/src/cpArray.c b/Chipmunk2D-7.0.2/src/cpArray.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpArray.c
@@ -0,0 +1,101 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <string.h>
+
+#include "chipmunk/chipmunk_private.h"
+
+
+cpArray *
+cpArrayNew(int size)
+{
+	cpArray *arr = (cpArray *)cpcalloc(1, sizeof(cpArray));
+	
+	arr->num = 0;
+	arr->max = (size ? size : 4);
+	arr->arr = (void **)cpcalloc(arr->max, sizeof(void*));
+	
+	return arr;
+}
+
+void
+cpArrayFree(cpArray *arr)
+{
+	if(arr){
+		cpfree(arr->arr);
+		arr->arr = NULL;
+		
+		cpfree(arr);
+	}
+}
+
+void
+cpArrayPush(cpArray *arr, void *object)
+{
+	if(arr->num == arr->max){
+		arr->max = 3*(arr->max + 1)/2;
+		arr->arr = (void **)cprealloc(arr->arr, arr->max*sizeof(void*));
+	}
+	
+	arr->arr[arr->num] = object;
+	arr->num++;
+}
+
+void *
+cpArrayPop(cpArray *arr)
+{
+	arr->num--;
+	
+	void *value = arr->arr[arr->num];
+	arr->arr[arr->num] = NULL;
+	
+	return value;
+}
+
+void
+cpArrayDeleteObj(cpArray *arr, void *obj)
+{
+	for(int i=0; i<arr->num; i++){
+		if(arr->arr[i] == obj){
+			arr->num--;
+			
+			arr->arr[i] = arr->arr[arr->num];
+			arr->arr[arr->num] = NULL;
+			
+			return;
+		}
+	}
+}
+
+void
+cpArrayFreeEach(cpArray *arr, void (freeFunc)(void*))
+{
+	for(int i=0; i<arr->num; i++) freeFunc(arr->arr[i]);
+}
+
+cpBool
+cpArrayContains(cpArray *arr, void *ptr)
+{
+	for(int i=0; i<arr->num; i++)
+		if(arr->arr[i] == ptr) return cpTrue;
+	
+	return cpFalse;
+}
diff --git a/Chipmunk2D-7.0.2/src/cpBBTree.c b/Chipmunk2D-7.0.2/src/cpBBTree.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpBBTree.c
@@ -0,0 +1,896 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "stdlib.h"
+#include "stdio.h"
+
+#include "chipmunk/chipmunk_private.h"
+
+static inline cpSpatialIndexClass *Klass();
+
+typedef struct Node Node;
+typedef struct Pair Pair;
+
+struct cpBBTree {
+	cpSpatialIndex spatialIndex;
+	cpBBTreeVelocityFunc velocityFunc;
+	
+	cpHashSet *leaves;
+	Node *root;
+	
+	Node *pooledNodes;
+	Pair *pooledPairs;
+	cpArray *allocatedBuffers;
+	
+	cpTimestamp stamp;
+};
+
+struct Node {
+	void *obj;
+	cpBB bb;
+	Node *parent;
+	
+	union {
+		// Internal nodes
+		struct { Node *a, *b; } children;
+		
+		// Leaves
+		struct {
+			cpTimestamp stamp;
+			Pair *pairs;
+		} leaf;
+	} node;
+};
+
+// Can't use anonymous unions and still get good x-compiler compatability
+#define A node.children.a
+#define B node.children.b
+#define STAMP node.leaf.stamp
+#define PAIRS node.leaf.pairs
+
+typedef struct Thread {
+	Pair *prev;
+	Node *leaf;
+	Pair *next;
+} Thread;
+
+struct Pair {
+	Thread a, b;
+	cpCollisionID id;
+};
+
+//MARK: Misc Functions
+
+static inline cpBB
+GetBB(cpBBTree *tree, void *obj)
+{
+	cpBB bb = tree->spatialIndex.bbfunc(obj);
+	
+	cpBBTreeVelocityFunc velocityFunc = tree->velocityFunc;
+	if(velocityFunc){
+		cpFloat coef = 0.1f;
+		cpFloat x = (bb.r - bb.l)*coef;
+		cpFloat y = (bb.t - bb.b)*coef;
+		
+		cpVect v = cpvmult(velocityFunc(obj), 0.1f);
+		return cpBBNew(bb.l + cpfmin(-x, v.x), bb.b + cpfmin(-y, v.y), bb.r + cpfmax(x, v.x), bb.t + cpfmax(y, v.y));
+	} else {
+		return bb;
+	}
+}
+
+static inline cpBBTree *
+GetTree(cpSpatialIndex *index)
+{
+	return (index && index->klass == Klass() ? (cpBBTree *)index : NULL);
+}
+
+static inline Node *
+GetRootIfTree(cpSpatialIndex *index){
+	return (index && index->klass == Klass() ? ((cpBBTree *)index)->root : NULL);
+}
+
+static inline cpBBTree *
+GetMasterTree(cpBBTree *tree)
+{
+	cpBBTree *dynamicTree = GetTree(tree->spatialIndex.dynamicIndex);
+	return (dynamicTree ? dynamicTree : tree);
+}
+
+static inline void
+IncrementStamp(cpBBTree *tree)
+{
+	cpBBTree *dynamicTree = GetTree(tree->spatialIndex.dynamicIndex);
+	if(dynamicTree){
+		dynamicTree->stamp++;
+	} else {
+		tree->stamp++;
+	}
+}
+
+//MARK: Pair/Thread Functions
+
+static void
+PairRecycle(cpBBTree *tree, Pair *pair)
+{
+	// Share the pool of the master tree.
+	// TODO: would be lovely to move the pairs stuff into an external data structure.
+	tree = GetMasterTree(tree);
+	
+	pair->a.next = tree->pooledPairs;
+	tree->pooledPairs = pair;
+}
+
+static Pair *
+PairFromPool(cpBBTree *tree)
+{
+	// Share the pool of the master tree.
+	// TODO: would be lovely to move the pairs stuff into an external data structure.
+	tree = GetMasterTree(tree);
+	
+	Pair *pair = tree->pooledPairs;
+	
+	if(pair){
+		tree->pooledPairs = pair->a.next;
+		return pair;
+	} else {
+		// Pool is exhausted, make more
+		int count = CP_BUFFER_BYTES/sizeof(Pair);
+		cpAssertHard(count, "Internal Error: Buffer size is too small.");
+		
+		Pair *buffer = (Pair *)cpcalloc(1, CP_BUFFER_BYTES);
+		cpArrayPush(tree->allocatedBuffers, buffer);
+		
+		// push all but the first one, return the first instead
+		for(int i=1; i<count; i++) PairRecycle(tree, buffer + i);
+		return buffer;
+	}
+}
+
+static inline void
+ThreadUnlink(Thread thread)
+{
+	Pair *next = thread.next;
+	Pair *prev = thread.prev;
+	
+	if(next){
+		if(next->a.leaf == thread.leaf) next->a.prev = prev; else next->b.prev = prev;
+	}
+	
+	if(prev){
+		if(prev->a.leaf == thread.leaf) prev->a.next = next; else prev->b.next = next;
+	} else {
+		thread.leaf->PAIRS = next;
+	}
+}
+
+static void
+PairsClear(Node *leaf, cpBBTree *tree)
+{
+	Pair *pair = leaf->PAIRS;
+	leaf->PAIRS = NULL;
+	
+	while(pair){
+		if(pair->a.leaf == leaf){
+			Pair *next = pair->a.next;
+			ThreadUnlink(pair->b);
+			PairRecycle(tree, pair);
+			pair = next;
+		} else {
+			Pair *next = pair->b.next;
+			ThreadUnlink(pair->a);
+			PairRecycle(tree, pair);
+			pair = next;
+		}
+	}
+}
+
+static void
+PairInsert(Node *a, Node *b, cpBBTree *tree)
+{
+	Pair *nextA = a->PAIRS, *nextB = b->PAIRS;
+	Pair *pair = PairFromPool(tree);
+	Pair temp = {{NULL, a, nextA},{NULL, b, nextB}, 0};
+	
+	a->PAIRS = b->PAIRS = pair;
+	*pair = temp;
+	
+	if(nextA){
+		if(nextA->a.leaf == a) nextA->a.prev = pair; else nextA->b.prev = pair;
+	}
+	
+	if(nextB){
+		if(nextB->a.leaf == b) nextB->a.prev = pair; else nextB->b.prev = pair;
+	}
+}
+
+
+//MARK: Node Functions
+
+static void
+NodeRecycle(cpBBTree *tree, Node *node)
+{
+	node->parent = tree->pooledNodes;
+	tree->pooledNodes = node;
+}
+
+static Node *
+NodeFromPool(cpBBTree *tree)
+{
+	Node *node = tree->pooledNodes;
+	
+	if(node){
+		tree->pooledNodes = node->parent;
+		return node;
+	} else {
+		// Pool is exhausted, make more
+		int count = CP_BUFFER_BYTES/sizeof(Node);
+		cpAssertHard(count, "Internal Error: Buffer size is too small.");
+		
+		Node *buffer = (Node *)cpcalloc(1, CP_BUFFER_BYTES);
+		cpArrayPush(tree->allocatedBuffers, buffer);
+		
+		// push all but the first one, return the first instead
+		for(int i=1; i<count; i++) NodeRecycle(tree, buffer + i);
+		return buffer;
+	}
+}
+
+static inline void
+NodeSetA(Node *node, Node *value)
+{
+	node->A = value;
+	value->parent = node;
+}
+
+static inline void
+NodeSetB(Node *node, Node *value)
+{
+	node->B = value;
+	value->parent = node;
+}
+
+static Node *
+NodeNew(cpBBTree *tree, Node *a, Node *b)
+{
+	Node *node = NodeFromPool(tree);
+	
+	node->obj = NULL;
+	node->bb = cpBBMerge(a->bb, b->bb);
+	node->parent = NULL;
+	
+	NodeSetA(node, a);
+	NodeSetB(node, b);
+	
+	return node;
+}
+
+static inline cpBool
+NodeIsLeaf(Node *node)
+{
+	return (node->obj != NULL);
+}
+
+static inline Node *
+NodeOther(Node *node, Node *child)
+{
+	return (node->A == child ? node->B : node->A);
+}
+
+static inline void
+NodeReplaceChild(Node *parent, Node *child, Node *value, cpBBTree *tree)
+{
+	cpAssertSoft(!NodeIsLeaf(parent), "Internal Error: Cannot replace child of a leaf.");
+	cpAssertSoft(child == parent->A || child == parent->B, "Internal Error: Node is not a child of parent.");
+	
+	if(parent->A == child){
+		NodeRecycle(tree, parent->A);
+		NodeSetA(parent, value);
+	} else {
+		NodeRecycle(tree, parent->B);
+		NodeSetB(parent, value);
+	}
+	
+	for(Node *node=parent; node; node = node->parent){
+		node->bb = cpBBMerge(node->A->bb, node->B->bb);
+	}
+}
+
+//MARK: Subtree Functions
+
+static inline cpFloat
+cpBBProximity(cpBB a, cpBB b)
+{
+	return cpfabs(a.l + a.r - b.l - b.r) + cpfabs(a.b + a.t - b.b - b.t);
+}
+
+static Node *
+SubtreeInsert(Node *subtree, Node *leaf, cpBBTree *tree)
+{
+	if(subtree == NULL){
+		return leaf;
+	} else if(NodeIsLeaf(subtree)){
+		return NodeNew(tree, leaf, subtree);
+	} else {
+		cpFloat cost_a = cpBBArea(subtree->B->bb) + cpBBMergedArea(subtree->A->bb, leaf->bb);
+		cpFloat cost_b = cpBBArea(subtree->A->bb) + cpBBMergedArea(subtree->B->bb, leaf->bb);
+		
+		if(cost_a == cost_b){
+			cost_a = cpBBProximity(subtree->A->bb, leaf->bb);
+			cost_b = cpBBProximity(subtree->B->bb, leaf->bb);
+		}
+		
+		if(cost_b < cost_a){
+			NodeSetB(subtree, SubtreeInsert(subtree->B, leaf, tree));
+		} else {
+			NodeSetA(subtree, SubtreeInsert(subtree->A, leaf, tree));
+		}
+		
+		subtree->bb = cpBBMerge(subtree->bb, leaf->bb);
+		return subtree;
+	}
+}
+
+static void
+SubtreeQuery(Node *subtree, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data)
+{
+	if(cpBBIntersects(subtree->bb, bb)){
+		if(NodeIsLeaf(subtree)){
+			func(obj, subtree->obj, 0, data);
+		} else {
+			SubtreeQuery(subtree->A, obj, bb, func, data);
+			SubtreeQuery(subtree->B, obj, bb, func, data);
+		}
+	}
+}
+
+
+static cpFloat
+SubtreeSegmentQuery(Node *subtree, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data)
+{
+	if(NodeIsLeaf(subtree)){
+		return func(obj, subtree->obj, data);
+	} else {
+		cpFloat t_a = cpBBSegmentQuery(subtree->A->bb, a, b);
+		cpFloat t_b = cpBBSegmentQuery(subtree->B->bb, a, b);
+		
+		if(t_a < t_b){
+			if(t_a < t_exit) t_exit = cpfmin(t_exit, SubtreeSegmentQuery(subtree->A, obj, a, b, t_exit, func, data));
+			if(t_b < t_exit) t_exit = cpfmin(t_exit, SubtreeSegmentQuery(subtree->B, obj, a, b, t_exit, func, data));
+		} else {
+			if(t_b < t_exit) t_exit = cpfmin(t_exit, SubtreeSegmentQuery(subtree->B, obj, a, b, t_exit, func, data));
+			if(t_a < t_exit) t_exit = cpfmin(t_exit, SubtreeSegmentQuery(subtree->A, obj, a, b, t_exit, func, data));
+		}
+		
+		return t_exit;
+	}
+}
+
+static void
+SubtreeRecycle(cpBBTree *tree, Node *node)
+{
+	if(!NodeIsLeaf(node)){
+		SubtreeRecycle(tree, node->A);
+		SubtreeRecycle(tree, node->B);
+		NodeRecycle(tree, node);
+	}
+}
+
+static inline Node *
+SubtreeRemove(Node *subtree, Node *leaf, cpBBTree *tree)
+{
+	if(leaf == subtree){
+		return NULL;
+	} else {
+		Node *parent = leaf->parent;
+		if(parent == subtree){
+			Node *other = NodeOther(subtree, leaf);
+			other->parent = subtree->parent;
+			NodeRecycle(tree, subtree);
+			return other;
+		} else {
+			NodeReplaceChild(parent->parent, parent, NodeOther(parent, leaf), tree);
+			return subtree;
+		}
+	}
+}
+
+//MARK: Marking Functions
+
+typedef struct MarkContext {
+	cpBBTree *tree;
+	Node *staticRoot;
+	cpSpatialIndexQueryFunc func;
+	void *data;
+} MarkContext;
+
+static void
+MarkLeafQuery(Node *subtree, Node *leaf, cpBool left, MarkContext *context)
+{
+	if(cpBBIntersects(leaf->bb, subtree->bb)){
+		if(NodeIsLeaf(subtree)){
+			if(left){
+				PairInsert(leaf, subtree, context->tree);
+			} else {
+				if(subtree->STAMP < leaf->STAMP) PairInsert(subtree, leaf, context->tree);
+				context->func(leaf->obj, subtree->obj, 0, context->data);
+			}
+		} else {
+			MarkLeafQuery(subtree->A, leaf, left, context);
+			MarkLeafQuery(subtree->B, leaf, left, context);
+		}
+	}
+}
+
+static void
+MarkLeaf(Node *leaf, MarkContext *context)
+{
+	cpBBTree *tree = context->tree;
+	if(leaf->STAMP == GetMasterTree(tree)->stamp){
+		Node *staticRoot = context->staticRoot;
+		if(staticRoot) MarkLeafQuery(staticRoot, leaf, cpFalse, context);
+		
+		for(Node *node = leaf; node->parent; node = node->parent){
+			if(node == node->parent->A){
+				MarkLeafQuery(node->parent->B, leaf, cpTrue, context);
+			} else {
+				MarkLeafQuery(node->parent->A, leaf, cpFalse, context);
+			}
+		}
+	} else {
+		Pair *pair = leaf->PAIRS;
+		while(pair){
+			if(leaf == pair->b.leaf){
+				pair->id = context->func(pair->a.leaf->obj, leaf->obj, pair->id, context->data);
+				pair = pair->b.next;
+			} else {
+				pair = pair->a.next;
+			}
+		}
+	}
+}
+
+static void
+MarkSubtree(Node *subtree, MarkContext *context)
+{
+	if(NodeIsLeaf(subtree)){
+		MarkLeaf(subtree, context);
+	} else {
+		MarkSubtree(subtree->A, context);
+		MarkSubtree(subtree->B, context); // TODO: Force TCO here?
+	}
+}
+
+//MARK: Leaf Functions
+
+static Node *
+LeafNew(cpBBTree *tree, void *obj, cpBB bb)
+{
+	Node *node = NodeFromPool(tree);
+	node->obj = obj;
+	node->bb = GetBB(tree, obj);
+	
+	node->parent = NULL;
+	node->STAMP = 0;
+	node->PAIRS = NULL;
+	
+	return node;
+}
+
+static cpBool
+LeafUpdate(Node *leaf, cpBBTree *tree)
+{
+	Node *root = tree->root;
+	cpBB bb = tree->spatialIndex.bbfunc(leaf->obj);
+	
+	if(!cpBBContainsBB(leaf->bb, bb)){
+		leaf->bb = GetBB(tree, leaf->obj);
+		
+		root = SubtreeRemove(root, leaf, tree);
+		tree->root = SubtreeInsert(root, leaf, tree);
+		
+		PairsClear(leaf, tree);
+		leaf->STAMP = GetMasterTree(tree)->stamp;
+		
+		return cpTrue;
+	} else {
+		return cpFalse;
+	}
+}
+
+static cpCollisionID VoidQueryFunc(void *obj1, void *obj2, cpCollisionID id, void *data){return id;}
+
+static void
+LeafAddPairs(Node *leaf, cpBBTree *tree)
+{
+	cpSpatialIndex *dynamicIndex = tree->spatialIndex.dynamicIndex;
+	if(dynamicIndex){
+		Node *dynamicRoot = GetRootIfTree(dynamicIndex);
+		if(dynamicRoot){
+			cpBBTree *dynamicTree = GetTree(dynamicIndex);
+			MarkContext context = {dynamicTree, NULL, NULL, NULL};
+			MarkLeafQuery(dynamicRoot, leaf, cpTrue, &context);
+		}
+	} else {
+		Node *staticRoot = GetRootIfTree(tree->spatialIndex.staticIndex);
+		MarkContext context = {tree, staticRoot, VoidQueryFunc, NULL};
+		MarkLeaf(leaf, &context);
+	}
+}
+
+//MARK: Memory Management Functions
+
+cpBBTree *
+cpBBTreeAlloc(void)
+{
+	return (cpBBTree *)cpcalloc(1, sizeof(cpBBTree));
+}
+
+static int
+leafSetEql(void *obj, Node *node)
+{
+	return (obj == node->obj);
+}
+
+static void *
+leafSetTrans(void *obj, cpBBTree *tree)
+{
+	return LeafNew(tree, obj, tree->spatialIndex.bbfunc(obj));
+}
+
+cpSpatialIndex *
+cpBBTreeInit(cpBBTree *tree, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
+{
+	cpSpatialIndexInit((cpSpatialIndex *)tree, Klass(), bbfunc, staticIndex);
+	
+	tree->velocityFunc = NULL;
+	
+	tree->leaves = cpHashSetNew(0, (cpHashSetEqlFunc)leafSetEql);
+	tree->root = NULL;
+	
+	tree->pooledNodes = NULL;
+	tree->allocatedBuffers = cpArrayNew(0);
+	
+	tree->stamp = 0;
+	
+	return (cpSpatialIndex *)tree;
+}
+
+void
+cpBBTreeSetVelocityFunc(cpSpatialIndex *index, cpBBTreeVelocityFunc func)
+{
+	if(index->klass != Klass()){
+		cpAssertWarn(cpFalse, "Ignoring cpBBTreeSetVelocityFunc() call to non-tree spatial index.");
+		return;
+	}
+	
+	((cpBBTree *)index)->velocityFunc = func;
+}
+
+cpSpatialIndex *
+cpBBTreeNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
+{
+	return cpBBTreeInit(cpBBTreeAlloc(), bbfunc, staticIndex);
+}
+
+static void
+cpBBTreeDestroy(cpBBTree *tree)
+{
+	cpHashSetFree(tree->leaves);
+	
+	if(tree->allocatedBuffers) cpArrayFreeEach(tree->allocatedBuffers, cpfree);
+	cpArrayFree(tree->allocatedBuffers);
+}
+
+//MARK: Insert/Remove
+
+static void
+cpBBTreeInsert(cpBBTree *tree, void *obj, cpHashValue hashid)
+{
+	Node *leaf = (Node *)cpHashSetInsert(tree->leaves, hashid, obj, (cpHashSetTransFunc)leafSetTrans, tree);
+	
+	Node *root = tree->root;
+	tree->root = SubtreeInsert(root, leaf, tree);
+	
+	leaf->STAMP = GetMasterTree(tree)->stamp;
+	LeafAddPairs(leaf, tree);
+	IncrementStamp(tree);
+}
+
+static void
+cpBBTreeRemove(cpBBTree *tree, void *obj, cpHashValue hashid)
+{
+	Node *leaf = (Node *)cpHashSetRemove(tree->leaves, hashid, obj);
+	
+	tree->root = SubtreeRemove(tree->root, leaf, tree);
+	PairsClear(leaf, tree);
+	NodeRecycle(tree, leaf);
+}
+
+static cpBool
+cpBBTreeContains(cpBBTree *tree, void *obj, cpHashValue hashid)
+{
+	return (cpHashSetFind(tree->leaves, hashid, obj) != NULL);
+}
+
+//MARK: Reindex
+
+static void LeafUpdateWrap(Node *leaf, cpBBTree *tree) {LeafUpdate(leaf, tree);}
+
+static void
+cpBBTreeReindexQuery(cpBBTree *tree, cpSpatialIndexQueryFunc func, void *data)
+{
+	if(!tree->root) return;
+	
+	// LeafUpdate() may modify tree->root. Don't cache it.
+	cpHashSetEach(tree->leaves, (cpHashSetIteratorFunc)LeafUpdateWrap, tree);
+	
+	cpSpatialIndex *staticIndex = tree->spatialIndex.staticIndex;
+	Node *staticRoot = (staticIndex && staticIndex->klass == Klass() ? ((cpBBTree *)staticIndex)->root : NULL);
+	
+	MarkContext context = {tree, staticRoot, func, data};
+	MarkSubtree(tree->root, &context);
+	if(staticIndex && !staticRoot) cpSpatialIndexCollideStatic((cpSpatialIndex *)tree, staticIndex, func, data);
+	
+	IncrementStamp(tree);
+}
+
+static void
+cpBBTreeReindex(cpBBTree *tree)
+{
+	cpBBTreeReindexQuery(tree, VoidQueryFunc, NULL);
+}
+
+static void
+cpBBTreeReindexObject(cpBBTree *tree, void *obj, cpHashValue hashid)
+{
+	Node *leaf = (Node *)cpHashSetFind(tree->leaves, hashid, obj);
+	if(leaf){
+		if(LeafUpdate(leaf, tree)) LeafAddPairs(leaf, tree);
+		IncrementStamp(tree);
+	}
+}
+
+//MARK: Query
+
+static void
+cpBBTreeSegmentQuery(cpBBTree *tree, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data)
+{
+	Node *root = tree->root;
+	if(root) SubtreeSegmentQuery(root, obj, a, b, t_exit, func, data);
+}
+
+static void
+cpBBTreeQuery(cpBBTree *tree, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data)
+{
+	if(tree->root) SubtreeQuery(tree->root, obj, bb, func, data);
+}
+
+//MARK: Misc
+
+static int
+cpBBTreeCount(cpBBTree *tree)
+{
+	return cpHashSetCount(tree->leaves);
+}
+
+typedef struct eachContext {
+	cpSpatialIndexIteratorFunc func;
+	void *data;
+} eachContext;
+
+static void each_helper(Node *node, eachContext *context){context->func(node->obj, context->data);}
+
+static void
+cpBBTreeEach(cpBBTree *tree, cpSpatialIndexIteratorFunc func, void *data)
+{
+	eachContext context = {func, data};
+	cpHashSetEach(tree->leaves, (cpHashSetIteratorFunc)each_helper, &context);
+}
+
+static cpSpatialIndexClass klass = {
+	(cpSpatialIndexDestroyImpl)cpBBTreeDestroy,
+	
+	(cpSpatialIndexCountImpl)cpBBTreeCount,
+	(cpSpatialIndexEachImpl)cpBBTreeEach,
+	
+	(cpSpatialIndexContainsImpl)cpBBTreeContains,
+	(cpSpatialIndexInsertImpl)cpBBTreeInsert,
+	(cpSpatialIndexRemoveImpl)cpBBTreeRemove,
+	
+	(cpSpatialIndexReindexImpl)cpBBTreeReindex,
+	(cpSpatialIndexReindexObjectImpl)cpBBTreeReindexObject,
+	(cpSpatialIndexReindexQueryImpl)cpBBTreeReindexQuery,
+	
+	(cpSpatialIndexQueryImpl)cpBBTreeQuery,
+	(cpSpatialIndexSegmentQueryImpl)cpBBTreeSegmentQuery,
+};
+
+static inline cpSpatialIndexClass *Klass(){return &klass;}
+
+
+//MARK: Tree Optimization
+
+static int
+cpfcompare(const cpFloat *a, const cpFloat *b){
+	return (*a < *b ? -1 : (*b < *a ? 1 : 0));
+}
+
+static void
+fillNodeArray(Node *node, Node ***cursor){
+	(**cursor) = node;
+	(*cursor)++;
+}
+
+static Node *
+partitionNodes(cpBBTree *tree, Node **nodes, int count)
+{
+	if(count == 1){
+		return nodes[0];
+	} else if(count == 2) {
+		return NodeNew(tree, nodes[0], nodes[1]);
+	}
+	
+	// Find the AABB for these nodes
+	cpBB bb = nodes[0]->bb;
+	for(int i=1; i<count; i++) bb = cpBBMerge(bb, nodes[i]->bb);
+	
+	// Split it on it's longest axis
+	cpBool splitWidth = (bb.r - bb.l > bb.t - bb.b);
+	
+	// Sort the bounds and use the median as the splitting point
+	cpFloat *bounds = (cpFloat *)cpcalloc(count*2, sizeof(cpFloat));
+	if(splitWidth){
+		for(int i=0; i<count; i++){
+			bounds[2*i + 0] = nodes[i]->bb.l;
+			bounds[2*i + 1] = nodes[i]->bb.r;
+		}
+	} else {
+		for(int i=0; i<count; i++){
+			bounds[2*i + 0] = nodes[i]->bb.b;
+			bounds[2*i + 1] = nodes[i]->bb.t;
+		}
+	}
+	
+	qsort(bounds, count*2, sizeof(cpFloat), (int (*)(const void *, const void *))cpfcompare);
+	cpFloat split = (bounds[count - 1] + bounds[count])*0.5f; // use the medain as the split
+	cpfree(bounds);
+
+	// Generate the child BBs
+	cpBB a = bb, b = bb;
+	if(splitWidth) a.r = b.l = split; else a.t = b.b = split;
+	
+	// Partition the nodes
+	int right = count;
+	for(int left=0; left < right;){
+		Node *node = nodes[left];
+		if(cpBBMergedArea(node->bb, b) < cpBBMergedArea(node->bb, a)){
+//		if(cpBBProximity(node->bb, b) < cpBBProximity(node->bb, a)){
+			right--;
+			nodes[left] = nodes[right];
+			nodes[right] = node;
+		} else {
+			left++;
+		}
+	}
+	
+	if(right == count){
+		Node *node = NULL;
+		for(int i=0; i<count; i++) node = SubtreeInsert(node, nodes[i], tree);
+		return node;
+	}
+	
+	// Recurse and build the node!
+	return NodeNew(tree,
+		partitionNodes(tree, nodes, right),
+		partitionNodes(tree, nodes + right, count - right)
+	);
+}
+
+//static void
+//cpBBTreeOptimizeIncremental(cpBBTree *tree, int passes)
+//{
+//	for(int i=0; i<passes; i++){
+//		Node *root = tree->root;
+//		Node *node = root;
+//		int bit = 0;
+//		unsigned int path = tree->opath;
+//		
+//		while(!NodeIsLeaf(node)){
+//			node = (path&(1<<bit) ? node->a : node->b);
+//			bit = (bit + 1)&(sizeof(unsigned int)*8 - 1);
+//		}
+//		
+//		root = subtreeRemove(root, node, tree);
+//		tree->root = subtreeInsert(root, node, tree);
+//	}
+//}
+
+void
+cpBBTreeOptimize(cpSpatialIndex *index)
+{
+	if(index->klass != &klass){
+		cpAssertWarn(cpFalse, "Ignoring cpBBTreeOptimize() call to non-tree spatial index.");
+		return;
+	}
+	
+	cpBBTree *tree = (cpBBTree *)index;
+	Node *root = tree->root;
+	if(!root) return;
+	
+	int count = cpBBTreeCount(tree);
+	Node **nodes = (Node **)cpcalloc(count, sizeof(Node *));
+	Node **cursor = nodes;
+	
+	cpHashSetEach(tree->leaves, (cpHashSetIteratorFunc)fillNodeArray, &cursor);
+	
+	SubtreeRecycle(tree, root);
+	tree->root = partitionNodes(tree, nodes, count);
+	cpfree(nodes);
+}
+
+//MARK: Debug Draw
+
+//#define CP_BBTREE_DEBUG_DRAW
+#ifdef CP_BBTREE_DEBUG_DRAW
+#include "OpenGL/gl.h"
+#include "OpenGL/glu.h"
+#include <GLUT/glut.h>
+
+static void
+NodeRender(Node *node, int depth)
+{
+	if(!NodeIsLeaf(node) && depth <= 10){
+		NodeRender(node->a, depth + 1);
+		NodeRender(node->b, depth + 1);
+	}
+	
+	cpBB bb = node->bb;
+	
+//	GLfloat v = depth/2.0f;	
+//	glColor3f(1.0f - v, v, 0.0f);
+	glLineWidth(cpfmax(5.0f - depth, 1.0f));
+	glBegin(GL_LINES); {
+		glVertex2f(bb.l, bb.b);
+		glVertex2f(bb.l, bb.t);
+		
+		glVertex2f(bb.l, bb.t);
+		glVertex2f(bb.r, bb.t);
+		
+		glVertex2f(bb.r, bb.t);
+		glVertex2f(bb.r, bb.b);
+		
+		glVertex2f(bb.r, bb.b);
+		glVertex2f(bb.l, bb.b);
+	}; glEnd();
+}
+
+void
+cpBBTreeRenderDebug(cpSpatialIndex *index){
+	if(index->klass != &klass){
+		cpAssertWarn(cpFalse, "Ignoring cpBBTreeRenderDebug() call to non-tree spatial index.");
+		return;
+	}
+	
+	cpBBTree *tree = (cpBBTree *)index;
+	if(tree->root) NodeRender(tree->root, 0);
+}
+#endif
diff --git a/Chipmunk2D-7.0.2/src/cpBody.c b/Chipmunk2D-7.0.2/src/cpBody.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpBody.c
@@ -0,0 +1,626 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <float.h>
+#include <stdarg.h>
+
+#include "chipmunk/chipmunk_private.h"
+
+cpBody*
+cpBodyAlloc(void)
+{
+	return (cpBody *)cpcalloc(1, sizeof(cpBody));
+}
+
+cpBody *
+cpBodyInit(cpBody *body, cpFloat mass, cpFloat moment)
+{
+	body->space = NULL;
+	body->shapeList = NULL;
+	body->arbiterList = NULL;
+	body->constraintList = NULL;
+	
+	body->velocity_func = cpBodyUpdateVelocity;
+	body->position_func = cpBodyUpdatePosition;
+	
+	body->sleeping.root = NULL;
+	body->sleeping.next = NULL;
+	body->sleeping.idleTime = 0.0f;
+	
+	body->p = cpvzero;
+	body->v = cpvzero;
+	body->f = cpvzero;
+	
+	body->w = 0.0f;
+	body->t = 0.0f;
+	
+	body->v_bias = cpvzero;
+	body->w_bias = 0.0f;
+	
+	body->userData = NULL;
+	
+	// Setters must be called after full initialization so the sanity checks don't assert on garbage data.
+	cpBodySetMass(body, mass);
+	cpBodySetMoment(body, moment);
+	cpBodySetAngle(body, 0.0f);
+	
+	return body;
+}
+
+cpBody*
+cpBodyNew(cpFloat mass, cpFloat moment)
+{
+	return cpBodyInit(cpBodyAlloc(), mass, moment);
+}
+
+cpBody*
+cpBodyNewKinematic()
+{
+	cpBody *body = cpBodyNew(0.0f, 0.0f);
+	cpBodySetType(body, CP_BODY_TYPE_KINEMATIC);
+	
+	return body;
+}
+
+cpBody*
+cpBodyNewStatic()
+{
+	cpBody *body = cpBodyNew(0.0f, 0.0f);
+	cpBodySetType(body, CP_BODY_TYPE_STATIC);
+	
+	return body;
+}
+
+void cpBodyDestroy(cpBody *body){}
+
+void
+cpBodyFree(cpBody *body)
+{
+	if(body){
+		cpBodyDestroy(body);
+		cpfree(body);
+	}
+}
+
+#ifdef NDEBUG
+	#define	cpAssertSaneBody(body)
+#else
+	static void cpv_assert_nan(cpVect v, char *message){cpAssertHard(v.x == v.x && v.y == v.y, message);}
+	static void cpv_assert_infinite(cpVect v, char *message){cpAssertHard(cpfabs(v.x) != INFINITY && cpfabs(v.y) != INFINITY, message);}
+	static void cpv_assert_sane(cpVect v, char *message){cpv_assert_nan(v, message); cpv_assert_infinite(v, message);}
+	
+	static void
+	cpBodySanityCheck(const cpBody *body)
+	{
+		cpAssertHard(body->m == body->m && body->m_inv == body->m_inv, "Body's mass is NaN.");
+		cpAssertHard(body->i == body->i && body->i_inv == body->i_inv, "Body's moment is NaN.");
+		cpAssertHard(body->m >= 0.0f, "Body's mass is negative.");
+		cpAssertHard(body->i >= 0.0f, "Body's moment is negative.");
+		
+		cpv_assert_sane(body->p, "Body's position is invalid.");
+		cpv_assert_sane(body->v, "Body's velocity is invalid.");
+		cpv_assert_sane(body->f, "Body's force is invalid.");
+
+		cpAssertHard(body->a == body->a && cpfabs(body->a) != INFINITY, "Body's angle is invalid.");
+		cpAssertHard(body->w == body->w && cpfabs(body->w) != INFINITY, "Body's angular velocity is invalid.");
+		cpAssertHard(body->t == body->t && cpfabs(body->t) != INFINITY, "Body's torque is invalid.");
+	}
+	
+	#define	cpAssertSaneBody(body) cpBodySanityCheck(body)
+#endif
+
+cpBool
+cpBodyIsSleeping(const cpBody *body)
+{
+	return (body->sleeping.root != ((cpBody*)0));
+}
+
+cpBodyType
+cpBodyGetType(cpBody *body)
+{
+	if(body->sleeping.idleTime == INFINITY){
+		return CP_BODY_TYPE_STATIC;
+	} else if(body->m == INFINITY){
+		return CP_BODY_TYPE_KINEMATIC;
+	} else {
+		return CP_BODY_TYPE_DYNAMIC;
+	}
+}
+
+void
+cpBodySetType(cpBody *body, cpBodyType type)
+{
+	cpBodyType oldType = cpBodyGetType(body);
+	if(oldType == type) return;
+	
+	// Static bodies have their idle timers set to infinity.
+	// Non-static bodies should have their idle timer reset.
+	body->sleeping.idleTime = (type == CP_BODY_TYPE_STATIC ? INFINITY : 0.0f);
+	
+	if(type == CP_BODY_TYPE_DYNAMIC){
+		body->m = body->i = 0.0f;
+		body->m_inv = body->i_inv = INFINITY;
+		
+		cpBodyAccumulateMassFromShapes(body);
+	} else {
+		body->m = body->i = INFINITY;
+		body->m_inv = body->i_inv = 0.0f;
+		
+		body->v = cpvzero;
+		body->w = 0.0f;
+	}
+	
+	// If the body is added to a space already, we'll need to update some space data structures.
+	cpSpace *space = cpBodyGetSpace(body);
+	if(space != NULL){
+		cpAssertSpaceUnlocked(space);
+		
+		if(oldType == CP_BODY_TYPE_STATIC){
+			// TODO This is probably not necessary
+//			cpBodyActivateStatic(body, NULL);
+		} else {
+			cpBodyActivate(body);
+		}
+		
+		// Move the bodies to the correct array.
+		cpArray *fromArray = cpSpaceArrayForBodyType(space, oldType);
+		cpArray *toArray = cpSpaceArrayForBodyType(space, type);
+		if(fromArray != toArray){
+			cpArrayDeleteObj(fromArray, body);
+			cpArrayPush(toArray, body);
+		}
+		
+		// Move the body's shapes to the correct spatial index.
+		cpSpatialIndex *fromIndex = (oldType == CP_BODY_TYPE_STATIC ? space->staticShapes : space->dynamicShapes);
+		cpSpatialIndex *toIndex = (type == CP_BODY_TYPE_STATIC ? space->staticShapes : space->dynamicShapes);
+		if(fromIndex != toIndex){
+			CP_BODY_FOREACH_SHAPE(body, shape){
+				cpSpatialIndexRemove(fromIndex, shape, shape->hashid);
+				cpSpatialIndexInsert(toIndex, shape, shape->hashid);
+			}
+		}
+	}
+}
+
+
+
+// Should *only* be called when shapes with mass info are modified, added or removed.
+void
+cpBodyAccumulateMassFromShapes(cpBody *body)
+{
+	if(body == NULL || cpBodyGetType(body) != CP_BODY_TYPE_DYNAMIC) return;
+	
+	// Reset the body's mass data.
+	body->m = body->i = 0.0f;
+	body->cog = cpvzero;
+	
+	// Cache the position to realign it at the end.
+	cpVect pos = cpBodyGetPosition(body);
+	
+	// Accumulate mass from shapes.
+	CP_BODY_FOREACH_SHAPE(body, shape){
+		struct cpShapeMassInfo *info = &shape->massInfo;
+		cpFloat m = info->m;
+		
+		if(m > 0.0f){
+			cpFloat msum = body->m + m;
+			
+			body->i += m*info->i + cpvdistsq(body->cog, info->cog)*(m*body->m)/msum;
+			body->cog = cpvlerp(body->cog, info->cog, m/msum);
+			body->m = msum;
+		}
+	}
+	
+	// Recalculate the inverses.
+	body->m_inv = 1.0f/body->m;
+	body->i_inv = 1.0f/body->i;
+	
+	// Realign the body since the CoG has probably moved.
+	cpBodySetPosition(body, pos);
+	cpAssertSaneBody(body);
+}
+
+cpSpace *
+cpBodyGetSpace(const cpBody *body)
+{
+	return body->space;
+}
+
+cpFloat
+cpBodyGetMass(const cpBody *body)
+{
+	return body->m;
+}
+
+void
+cpBodySetMass(cpBody *body, cpFloat mass)
+{
+	cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "You cannot set the mass of kinematic or static bodies.");
+	cpAssertHard(0.0f <= mass && mass < INFINITY, "Mass must be positive and finite.");
+	
+	cpBodyActivate(body);
+	body->m = mass;
+	body->m_inv = 1.0f/mass;
+	cpAssertSaneBody(body);
+}
+
+cpFloat
+cpBodyGetMoment(const cpBody *body)
+{
+	return body->i;
+}
+
+void
+cpBodySetMoment(cpBody *body, cpFloat moment)
+{
+	cpAssertHard(moment >= 0.0f, "Moment of Inertia must be positive.");
+	
+	cpBodyActivate(body);
+	body->i = moment;
+	body->i_inv = 1.0f/moment;
+	cpAssertSaneBody(body);
+}
+
+cpVect
+cpBodyGetRotation(const cpBody *body)
+{
+	return cpv(body->transform.a, body->transform.b);
+}
+
+void
+cpBodyAddShape(cpBody *body, cpShape *shape)
+{
+	cpShape *next = body->shapeList;
+	if(next) next->prev = shape;
+	
+	shape->next = next;
+	body->shapeList = shape;
+	
+	if(shape->massInfo.m > 0.0f){
+		cpBodyAccumulateMassFromShapes(body);
+	}
+}
+
+void
+cpBodyRemoveShape(cpBody *body, cpShape *shape)
+{
+  cpShape *prev = shape->prev;
+  cpShape *next = shape->next;
+  
+  if(prev){
+		prev->next = next;
+  } else {
+		body->shapeList = next;
+  }
+  
+  if(next){
+		next->prev = prev;
+	}
+  
+  shape->prev = NULL;
+  shape->next = NULL;
+	
+	if(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC && shape->massInfo.m > 0.0f){
+		cpBodyAccumulateMassFromShapes(body);
+	}
+}
+
+static cpConstraint *
+filterConstraints(cpConstraint *node, cpBody *body, cpConstraint *filter)
+{
+	if(node == filter){
+		return cpConstraintNext(node, body);
+	} else if(node->a == body){
+		node->next_a = filterConstraints(node->next_a, body, filter);
+	} else {
+		node->next_b = filterConstraints(node->next_b, body, filter);
+	}
+	
+	return node;
+}
+
+void
+cpBodyRemoveConstraint(cpBody *body, cpConstraint *constraint)
+{
+	body->constraintList = filterConstraints(body->constraintList, body, constraint);
+}
+
+// 'p' is the position of the CoG
+static void
+SetTransform(cpBody *body, cpVect p, cpFloat a)
+{
+	cpVect rot = cpvforangle(a);
+	cpVect c = body->cog;
+	
+	body->transform = cpTransformNewTranspose(
+		rot.x, -rot.y, p.x - (c.x*rot.x - c.y*rot.y),
+		rot.y,  rot.x, p.y - (c.x*rot.y + c.y*rot.x)
+	);
+}
+
+static inline cpFloat
+SetAngle(cpBody *body, cpFloat a)
+{
+	body->a = a;
+	cpAssertSaneBody(body);
+	
+	return a;
+}
+
+cpVect
+cpBodyGetPosition(const cpBody *body)
+{
+	return cpTransformPoint(body->transform, cpvzero);
+}
+
+void
+cpBodySetPosition(cpBody *body, cpVect position)
+{
+	cpBodyActivate(body);
+	cpVect p = body->p = cpvadd(cpTransformVect(body->transform, body->cog), position);
+	cpAssertSaneBody(body);
+	
+	SetTransform(body, p, body->a);
+}
+
+cpVect
+cpBodyGetCenterOfGravity(const cpBody *body)
+{
+	return body->cog;
+}
+
+void
+cpBodySetCenterOfGravity(cpBody *body, cpVect cog)
+{
+	cpBodyActivate(body);
+	body->cog = cog;
+	cpAssertSaneBody(body);
+}
+
+cpVect
+cpBodyGetVelocity(const cpBody *body)
+{
+	return body->v;
+}
+
+void
+cpBodySetVelocity(cpBody *body, cpVect velocity)
+{
+	cpBodyActivate(body);
+	body->v = velocity;
+	cpAssertSaneBody(body);
+}
+
+cpVect
+cpBodyGetForce(const cpBody *body)
+{
+	return body->f;
+}
+
+void
+cpBodySetForce(cpBody *body, cpVect force)
+{
+	cpBodyActivate(body);
+	body->f = force;
+	cpAssertSaneBody(body);
+}
+
+cpFloat
+cpBodyGetAngle(const cpBody *body)
+{
+	return body->a;
+}
+
+void
+cpBodySetAngle(cpBody *body, cpFloat angle)
+{
+	cpBodyActivate(body);
+	SetAngle(body, angle);
+	
+	SetTransform(body, body->p, angle);
+}
+
+cpFloat
+cpBodyGetAngularVelocity(const cpBody *body)
+{
+	return body->w;
+}
+
+void
+cpBodySetAngularVelocity(cpBody *body, cpFloat angularVelocity)
+{
+	cpBodyActivate(body);
+	body->w = angularVelocity;
+	cpAssertSaneBody(body);
+}
+
+cpFloat
+cpBodyGetTorque(const cpBody *body)
+{
+	return body->t;
+}
+
+void
+cpBodySetTorque(cpBody *body, cpFloat torque)
+{
+	cpBodyActivate(body);
+	body->t = torque;
+	cpAssertSaneBody(body);
+}
+
+cpDataPointer
+cpBodyGetUserData(const cpBody *body)
+{
+	return body->userData;
+}
+
+void
+cpBodySetUserData(cpBody *body, cpDataPointer userData)
+{
+	body->userData = userData;
+}
+
+void
+cpBodySetVelocityUpdateFunc(cpBody *body, cpBodyVelocityFunc velocityFunc)
+{
+	body->velocity_func = velocityFunc;
+}
+
+void
+cpBodySetPositionUpdateFunc(cpBody *body, cpBodyPositionFunc positionFunc)
+{
+	body->position_func = positionFunc;
+}
+
+void
+cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
+{
+	// Skip kinematic bodies.
+	if(cpBodyGetType(body) == CP_BODY_TYPE_KINEMATIC) return;
+	
+	cpAssertSoft(body->m > 0.0f && body->i > 0.0f, "Body's mass and moment must be positive to simulate. (Mass: %f Moment: %f)", body->m, body->i);
+	
+	body->v = cpvadd(cpvmult(body->v, damping), cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), dt));
+	body->w = body->w*damping + body->t*body->i_inv*dt;
+	
+	// Reset forces.
+	body->f = cpvzero;
+	body->t = 0.0f;
+	
+	cpAssertSaneBody(body);
+}
+
+void
+cpBodyUpdatePosition(cpBody *body, cpFloat dt)
+{
+	cpVect p = body->p = cpvadd(body->p, cpvmult(cpvadd(body->v, body->v_bias), dt));
+	cpFloat a = SetAngle(body, body->a + (body->w + body->w_bias)*dt);
+	SetTransform(body, p, a);
+	
+	body->v_bias = cpvzero;
+	body->w_bias = 0.0f;
+	
+	cpAssertSaneBody(body);
+}
+
+cpVect
+cpBodyLocalToWorld(const cpBody *body, const cpVect point)
+{
+	return cpTransformPoint(body->transform, point);
+}
+
+cpVect
+cpBodyWorldToLocal(const cpBody *body, const cpVect point)
+{
+	return cpTransformPoint(cpTransformRigidInverse(body->transform), point);
+}
+
+void
+cpBodyApplyForceAtWorldPoint(cpBody *body, cpVect force, cpVect point)
+{
+	cpBodyActivate(body);
+	body->f = cpvadd(body->f, force);
+	
+	cpVect r = cpvsub(point, cpTransformPoint(body->transform, body->cog));
+	body->t += cpvcross(r, force);
+}
+
+void
+cpBodyApplyForceAtLocalPoint(cpBody *body, cpVect force, cpVect point)
+{
+	cpBodyApplyForceAtWorldPoint(body, cpTransformVect(body->transform, force), cpTransformPoint(body->transform, point));
+}
+
+void
+cpBodyApplyImpulseAtWorldPoint(cpBody *body, cpVect impulse, cpVect point)
+{
+	cpBodyActivate(body);
+	
+	cpVect r = cpvsub(point, cpTransformPoint(body->transform, body->cog));
+	apply_impulse(body, impulse, r);
+}
+
+void
+cpBodyApplyImpulseAtLocalPoint(cpBody *body, cpVect impulse, cpVect point)
+{
+	cpBodyApplyImpulseAtWorldPoint(body, cpTransformVect(body->transform, impulse), cpTransformPoint(body->transform, point));
+}
+
+cpVect
+cpBodyGetVelocityAtLocalPoint(const cpBody *body, cpVect point)
+{
+	cpVect r = cpTransformVect(body->transform, cpvsub(point, body->cog));
+	return cpvadd(body->v, cpvmult(cpvperp(r), body->w));
+}
+
+cpVect
+cpBodyGetVelocityAtWorldPoint(const cpBody *body, cpVect point)
+{
+	cpVect r = cpvsub(point, cpTransformPoint(body->transform, body->cog));
+	return cpvadd(body->v, cpvmult(cpvperp(r), body->w));
+}
+
+cpFloat
+cpBodyKineticEnergy(const cpBody *body)
+{
+	// Need to do some fudging to avoid NaNs
+	cpFloat vsq = cpvdot(body->v, body->v);
+	cpFloat wsq = body->w*body->w;
+	return (vsq ? vsq*body->m : 0.0f) + (wsq ? wsq*body->i : 0.0f);
+}
+
+void
+cpBodyEachShape(cpBody *body, cpBodyShapeIteratorFunc func, void *data)
+{
+	cpShape *shape = body->shapeList;
+	while(shape){
+		cpShape *next = shape->next;
+		func(body, shape, data);
+		shape = next;
+	}
+}
+
+void
+cpBodyEachConstraint(cpBody *body, cpBodyConstraintIteratorFunc func, void *data)
+{
+	cpConstraint *constraint = body->constraintList;
+	while(constraint){
+		cpConstraint *next = cpConstraintNext(constraint, body);
+		func(body, constraint, data);
+		constraint = next;
+	}
+}
+
+void
+cpBodyEachArbiter(cpBody *body, cpBodyArbiterIteratorFunc func, void *data)
+{
+	cpArbiter *arb = body->arbiterList;
+	while(arb){
+		cpArbiter *next = cpArbiterNext(arb, body);
+		
+		cpBool swapped = arb->swapped; {
+			arb->swapped = (body == arb->body_b);
+			func(body, arb, data);
+		} arb->swapped = swapped;
+		
+		arb = next;
+	}
+}
diff --git a/Chipmunk2D-7.0.2/src/cpCollision.c b/Chipmunk2D-7.0.2/src/cpCollision.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpCollision.c
@@ -0,0 +1,726 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "chipmunk/chipmunk_private.h"
+#include "chipmunk/cpRobust.h"
+
+#if DEBUG && 0
+#include "ChipmunkDemo.h"
+#define DRAW_ALL 0
+#define DRAW_GJK (0 || DRAW_ALL)
+#define DRAW_EPA (0 || DRAW_ALL)
+#define DRAW_CLOSEST (0 || DRAW_ALL)
+#define DRAW_CLIP (0 || DRAW_ALL)
+
+#define PRINT_LOG 0
+#endif
+
+#define MAX_GJK_ITERATIONS 30
+#define MAX_EPA_ITERATIONS 30
+#define WARN_GJK_ITERATIONS 20
+#define WARN_EPA_ITERATIONS 20
+
+static inline void
+cpCollisionInfoPushContact(struct cpCollisionInfo *info, cpVect p1, cpVect p2, cpHashValue hash)
+{
+	cpAssertSoft(info->count <= CP_MAX_CONTACTS_PER_ARBITER, "Internal error: Tried to push too many contacts.");
+	
+	struct cpContact *con = &info->arr[info->count];
+	con->r1 = p1;
+	con->r2 = p2;
+	con->hash = hash;
+	
+	info->count++;
+}
+
+//MARK: Support Points and Edges:
+
+// Support points are the maximal points on a shape's perimeter along a certain axis.
+// The GJK and EPA algorithms use support points to iteratively sample the surface of the two shapes' minkowski difference.
+
+static inline int
+PolySupportPointIndex(const int count, const struct cpSplittingPlane *planes, const cpVect n)
+{
+	cpFloat max = -INFINITY;
+	int index = 0;
+	
+	for(int i=0; i<count; i++){
+		cpVect v = planes[i].v0;
+		cpFloat d = cpvdot(v, n);
+		if(d > max){
+			max = d;
+			index = i;
+		}
+	}
+	
+	return index;
+}
+
+struct SupportPoint {
+	cpVect p;
+	// Save an index of the point so it can be cheaply looked up as a starting point for the next frame.
+	cpCollisionID index;
+};
+
+static inline struct SupportPoint
+SupportPointNew(cpVect p, cpCollisionID index)
+{
+	struct SupportPoint point = {p, index};
+	return point;
+}
+
+typedef struct SupportPoint (*SupportPointFunc)(const cpShape *shape, const cpVect n);
+
+static inline struct SupportPoint
+CircleSupportPoint(const cpCircleShape *circle, const cpVect n)
+{
+	return SupportPointNew(circle->tc, 0);
+}
+
+static inline struct SupportPoint
+SegmentSupportPoint(const cpSegmentShape *seg, const cpVect n)
+{
+	if(cpvdot(seg->ta, n) > cpvdot(seg->tb, n)){
+		return SupportPointNew(seg->ta, 0);
+	} else {
+		return SupportPointNew(seg->tb, 1);
+	}
+}
+
+static inline struct SupportPoint
+PolySupportPoint(const cpPolyShape *poly, const cpVect n)
+{
+	const struct cpSplittingPlane *planes = poly->planes;
+	int i = PolySupportPointIndex(poly->count, planes, n);
+	return SupportPointNew(planes[i].v0, i);
+}
+
+// A point on the surface of two shape's minkowski difference.
+struct MinkowskiPoint {
+	// Cache the two original support points.
+	cpVect a, b;
+	// b - a
+	cpVect ab;
+	// Concatenate the two support point indexes.
+	cpCollisionID id;
+};
+
+static inline struct MinkowskiPoint
+MinkowskiPointNew(const struct SupportPoint a, const struct SupportPoint b)
+{
+	struct MinkowskiPoint point = {a.p, b.p, cpvsub(b.p, a.p), (a.index & 0xFF)<<8 | (b.index & 0xFF)};
+	return point;
+}
+
+struct SupportContext {
+	const cpShape *shape1, *shape2;
+	SupportPointFunc func1, func2;
+};
+
+// Calculate the maximal point on the minkowski difference of two shapes along a particular axis.
+static inline struct MinkowskiPoint
+Support(const struct SupportContext *ctx, const cpVect n)
+{
+	struct SupportPoint a = ctx->func1(ctx->shape1, cpvneg(n));
+	struct SupportPoint b = ctx->func2(ctx->shape2, n);
+	return MinkowskiPointNew(a, b);
+}
+
+struct EdgePoint {
+	cpVect p;
+	// Keep a hash value for Chipmunk's collision hashing mechanism.
+	cpHashValue hash;
+};
+
+// Support edges are the edges of a polygon or segment shape that are in contact.
+struct Edge {
+	struct EdgePoint a, b;
+	cpFloat r;
+	cpVect n;
+};
+
+static struct Edge
+SupportEdgeForPoly(const cpPolyShape *poly, const cpVect n)
+{
+	int count = poly->count;
+	int i1 = PolySupportPointIndex(poly->count, poly->planes, n);
+	
+	// TODO: get rid of mod eventually, very expensive on ARM
+	int i0 = (i1 - 1 + count)%count;
+	int i2 = (i1 + 1)%count;
+	
+	const struct cpSplittingPlane *planes = poly->planes;
+	cpHashValue hashid = poly->shape.hashid;
+	if(cpvdot(n, planes[i1].n) > cpvdot(n, planes[i2].n)){
+		struct Edge edge = {{planes[i0].v0, CP_HASH_PAIR(hashid, i0)}, {planes[i1].v0, CP_HASH_PAIR(hashid, i1)}, poly->r, planes[i1].n};
+		return edge;
+	} else {
+		struct Edge edge = {{planes[i1].v0, CP_HASH_PAIR(hashid, i1)}, {planes[i2].v0, CP_HASH_PAIR(hashid, i2)}, poly->r, planes[i2].n};
+		return edge;
+	}
+}
+
+static struct Edge
+SupportEdgeForSegment(const cpSegmentShape *seg, const cpVect n)
+{
+	cpHashValue hashid = seg->shape.hashid;
+	if(cpvdot(seg->tn, n) > 0.0){
+		struct Edge edge = {{seg->ta, CP_HASH_PAIR(hashid, 0)}, {seg->tb, CP_HASH_PAIR(hashid, 1)}, seg->r, seg->tn};
+		return edge;
+	} else {
+		struct Edge edge = {{seg->tb, CP_HASH_PAIR(hashid, 1)}, {seg->ta, CP_HASH_PAIR(hashid, 0)}, seg->r, cpvneg(seg->tn)};
+		return edge;
+	}
+}
+
+// Find the closest p(t) to (0, 0) where p(t) = a*(1-t)/2 + b*(1+t)/2
+// The range for t is [-1, 1] to avoid floating point issues if the parameters are swapped.
+static inline cpFloat
+ClosestT(const cpVect a, const cpVect b)
+{
+	cpVect delta = cpvsub(b, a);
+	return -cpfclamp(cpvdot(delta, cpvadd(a, b))/cpvlengthsq(delta), -1.0f, 1.0f);
+}
+
+// Basically the same as cpvlerp(), except t = [-1, 1]
+static inline cpVect
+LerpT(const cpVect a, const cpVect b, const cpFloat t)
+{
+	cpFloat ht = 0.5f*t;
+	return cpvadd(cpvmult(a, 0.5f - ht), cpvmult(b, 0.5f + ht));
+}
+
+// Closest points on the surface of two shapes.
+struct ClosestPoints {
+	// Surface points in absolute coordinates.
+	cpVect a, b;
+	// Minimum separating axis of the two shapes.
+	cpVect n;
+	// Signed distance between the points.
+	cpFloat d;
+	// Concatenation of the id's of the minkoski points.
+	cpCollisionID id;
+};
+
+// Calculate the closest points on two shapes given the closest edge on their minkowski difference to (0, 0)
+static inline struct ClosestPoints
+ClosestPointsNew(const struct MinkowskiPoint v0, const struct MinkowskiPoint v1)
+{
+	// Find the closest p(t) on the minkowski difference to (0, 0)
+	cpFloat t = ClosestT(v0.ab, v1.ab);
+	cpVect p = LerpT(v0.ab, v1.ab, t);
+	
+	// Interpolate the original support points using the same 't' value as above.
+	// This gives you the closest surface points in absolute coordinates. NEAT!
+	cpVect pa = LerpT(v0.a, v1.a, t);
+	cpVect pb = LerpT(v0.b, v1.b, t);
+	cpCollisionID id = (v0.id & 0xFFFF)<<16 | (v1.id & 0xFFFF);
+	
+	// First try calculating the MSA from the minkowski difference edge.
+	// This gives us a nice, accurate MSA when the surfaces are close together.
+	cpVect delta = cpvsub(v1.ab, v0.ab);
+	cpVect n = cpvnormalize(cpvrperp(delta));
+	cpFloat d = cpvdot(n, p);
+	
+	if(d <= 0.0f || (-1.0f < t && t < 1.0f)){
+		// If the shapes are overlapping, or we have a regular vertex/edge collision, we are done.
+		struct ClosestPoints points = {pa, pb, n, d, id};
+		return points;
+	} else {
+		// Vertex/vertex collisions need special treatment since the MSA won't be shared with an axis of the minkowski difference.
+		cpFloat d2 = cpvlength(p);
+		cpVect n2 = cpvmult(p, 1.0f/(d2 + CPFLOAT_MIN));
+		
+		struct ClosestPoints points = {pa, pb, n2, d2, id};
+		return points;
+	}
+}
+
+//MARK: EPA Functions
+
+static inline cpFloat
+ClosestDist(const cpVect v0,const cpVect v1)
+{
+	return cpvlengthsq(LerpT(v0, v1, ClosestT(v0, v1)));
+}
+
+// Recursive implementation of the EPA loop.
+// Each recursion adds a point to the convex hull until it's known that we have the closest point on the surface.
+static struct ClosestPoints
+EPARecurse(const struct SupportContext *ctx, const int count, const struct MinkowskiPoint *hull, const int iteration)
+{
+	int mini = 0;
+	cpFloat minDist = INFINITY;
+	
+	// TODO: precalculate this when building the hull and save a step.
+	// Find the closest segment hull[i] and hull[i + 1] to (0, 0)
+	for(int j=0, i=count-1; j<count; i=j, j++){
+		cpFloat d = ClosestDist(hull[i].ab, hull[j].ab);
+		if(d < minDist){
+			minDist = d;
+			mini = i;
+		}
+	}
+	
+	struct MinkowskiPoint v0 = hull[mini];
+	struct MinkowskiPoint v1 = hull[(mini + 1)%count];
+	cpAssertSoft(!cpveql(v0.ab, v1.ab), "Internal Error: EPA vertexes are the same (%d and %d)", mini, (mini + 1)%count);
+	
+	// Check if there is a point on the minkowski difference beyond this edge.
+	struct MinkowskiPoint p = Support(ctx, cpvperp(cpvsub(v1.ab, v0.ab)));
+	
+#if DRAW_EPA
+	cpVect verts[count];
+	for(int i=0; i<count; i++) verts[i] = hull[i].ab;
+	
+	ChipmunkDebugDrawPolygon(count, verts, 0.0, RGBAColor(1, 1, 0, 1), RGBAColor(1, 1, 0, 0.25));
+	ChipmunkDebugDrawSegment(v0.ab, v1.ab, RGBAColor(1, 0, 0, 1));
+	
+	ChipmunkDebugDrawDot(5, p.ab, LAColor(1, 1));
+#endif
+	
+	// The usual exit condition is a duplicated vertex.
+	// Much faster to check the ids than to check the signed area.
+	cpBool duplicate = (p.id == v0.id || p.id == v1.id);
+	
+	if(!duplicate && cpCheckPointGreater(v0.ab, v1.ab, p.ab) && iteration < MAX_EPA_ITERATIONS){
+		// Rebuild the convex hull by inserting p.
+		struct MinkowskiPoint *hull2 = (struct MinkowskiPoint *)alloca((count + 1)*sizeof(struct MinkowskiPoint));
+		int count2 = 1;
+		hull2[0] = p;
+		
+		for(int i=0; i<count; i++){
+			int index = (mini + 1 + i)%count;
+			
+			cpVect h0 = hull2[count2 - 1].ab;
+			cpVect h1 = hull[index].ab;
+			cpVect h2 = (i + 1 < count ? hull[(index + 1)%count] : p).ab;
+			
+			if(cpCheckPointGreater(h0, h2, h1)){
+				hull2[count2] = hull[index];
+				count2++;
+			}
+		}
+		
+		return EPARecurse(ctx, count2, hull2, iteration + 1);
+	} else {
+		// Could not find a new point to insert, so we have found the closest edge of the minkowski difference.
+		cpAssertWarn(iteration < WARN_EPA_ITERATIONS, "High EPA iterations: %d", iteration);
+		return ClosestPointsNew(v0, v1);
+	}
+}
+
+// Find the closest points on the surface of two overlapping shapes using the EPA algorithm.
+// EPA is called from GJK when two shapes overlap.
+// This is a moderately expensive step! Avoid it by adding radii to your shapes so their inner polygons won't overlap.
+static struct ClosestPoints
+EPA(const struct SupportContext *ctx, const struct MinkowskiPoint v0, const struct MinkowskiPoint v1, const struct MinkowskiPoint v2)
+{
+	// TODO: allocate a NxM array here and do an in place convex hull reduction in EPARecurse?
+	struct MinkowskiPoint hull[3] = {v0, v1, v2};
+	return EPARecurse(ctx, 3, hull, 1);
+}
+
+//MARK: GJK Functions.
+
+// Recursive implementation of the GJK loop.
+static inline struct ClosestPoints
+GJKRecurse(const struct SupportContext *ctx, const struct MinkowskiPoint v0, const struct MinkowskiPoint v1, const int iteration)
+{
+	if(iteration > MAX_GJK_ITERATIONS){
+		cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK iterations: %d", iteration);
+		return ClosestPointsNew(v0, v1);
+	}
+	
+	if(cpCheckPointGreater(v1.ab, v0.ab, cpvzero)){
+		// Origin is behind axis. Flip and try again.
+		return GJKRecurse(ctx, v1, v0, iteration);
+	} else {
+		cpFloat t = ClosestT(v0.ab, v1.ab);
+		cpVect n = (-1.0f < t && t < 1.0f ? cpvperp(cpvsub(v1.ab, v0.ab)) : cpvneg(LerpT(v0.ab, v1.ab, t)));
+		struct MinkowskiPoint p = Support(ctx, n);
+		
+#if DRAW_GJK
+		ChipmunkDebugDrawSegment(v0.ab, v1.ab, RGBAColor(1, 1, 1, 1));
+		cpVect c = cpvlerp(v0.ab, v1.ab, 0.5);
+		ChipmunkDebugDrawSegment(c, cpvadd(c, cpvmult(cpvnormalize(n), 5.0)), RGBAColor(1, 0, 0, 1));
+		
+		ChipmunkDebugDrawDot(5.0, p.ab, LAColor(1, 1));
+#endif
+		
+		if(cpCheckPointGreater(p.ab, v0.ab, cpvzero) && cpCheckPointGreater(v1.ab, p.ab, cpvzero)){
+			// The triangle v0, p, v1 contains the origin. Use EPA to find the MSA.
+			cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK->EPA iterations: %d", iteration);
+			return EPA(ctx, v0, p, v1);
+		} else {
+			if(cpCheckAxis(v0.ab, v1.ab, p.ab, n)){
+				// The edge v0, v1 that we already have is the closest to (0, 0) since p was not closer.
+				cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK iterations: %d", iteration);
+				return ClosestPointsNew(v0, v1);
+			} else {
+				// p was closer to the origin than our existing edge.
+				// Need to figure out which existing point to drop.
+				if(ClosestDist(v0.ab, p.ab) < ClosestDist(p.ab, v1.ab)){
+					return GJKRecurse(ctx, v0, p, iteration + 1);
+				} else {
+					return GJKRecurse(ctx, p, v1, iteration + 1);
+				}
+			}
+		}
+	}
+}
+
+// Get a SupportPoint from a cached shape and index.
+static struct SupportPoint
+ShapePoint(const cpShape *shape, const int i)
+{
+	switch(shape->klass->type){
+		case CP_CIRCLE_SHAPE: {
+			return SupportPointNew(((cpCircleShape *)shape)->tc, 0);
+		} case CP_SEGMENT_SHAPE: {
+			cpSegmentShape *seg = (cpSegmentShape *)shape;
+			return SupportPointNew(i == 0 ? seg->ta : seg->tb, i);
+		} case CP_POLY_SHAPE: {
+			cpPolyShape *poly = (cpPolyShape *)shape;
+			// Poly shapes may change vertex count.
+			int index = (i < poly->count ? i : 0);
+			return SupportPointNew(poly->planes[index].v0, index);
+		} default: {
+			return SupportPointNew(cpvzero, 0);
+		}
+	}
+}
+
+// Find the closest points between two shapes using the GJK algorithm.
+static struct ClosestPoints
+GJK(const struct SupportContext *ctx, cpCollisionID *id)
+{
+#if DRAW_GJK || DRAW_EPA
+	int count1 = 1;
+	int count2 = 1;
+	
+	switch(ctx->shape1->klass->type){
+		case CP_SEGMENT_SHAPE: count1 = 2; break;
+		case CP_POLY_SHAPE: count1 = ((cpPolyShape *)ctx->shape1)->count; break;
+		default: break;
+	}
+	
+	switch(ctx->shape2->klass->type){
+		case CP_SEGMENT_SHAPE: count1 = 2; break;
+		case CP_POLY_SHAPE: count2 = ((cpPolyShape *)ctx->shape2)->count; break;
+		default: break;
+	}
+	
+	
+	// draw the minkowski difference origin
+	cpVect origin = cpvzero;
+	ChipmunkDebugDrawDot(5.0, origin, RGBAColor(1,0,0,1));
+	
+	int mdiffCount = count1*count2;
+	cpVect *mdiffVerts = alloca(mdiffCount*sizeof(cpVect));
+	
+	for(int i=0; i<count1; i++){
+		for(int j=0; j<count2; j++){
+			cpVect v = cpvsub(ShapePoint(ctx->shape2, j).p, ShapePoint(ctx->shape1, i).p);
+			mdiffVerts[i*count2 + j] = v;
+			ChipmunkDebugDrawDot(2.0, v, RGBAColor(1, 0, 0, 1));
+		}
+	}
+	 
+	cpVect *hullVerts = alloca(mdiffCount*sizeof(cpVect));
+	int hullCount = cpConvexHull(mdiffCount, mdiffVerts, hullVerts, NULL, 0.0);
+	
+	ChipmunkDebugDrawPolygon(hullCount, hullVerts, 0.0, RGBAColor(1, 0, 0, 1), RGBAColor(1, 0, 0, 0.25));
+#endif
+	
+	struct MinkowskiPoint v0, v1;
+	if(*id){
+		// Use the minkowski points from the last frame as a starting point using the cached indexes.
+		v0 = MinkowskiPointNew(ShapePoint(ctx->shape1, (*id>>24)&0xFF), ShapePoint(ctx->shape2, (*id>>16)&0xFF));
+		v1 = MinkowskiPointNew(ShapePoint(ctx->shape1, (*id>> 8)&0xFF), ShapePoint(ctx->shape2, (*id    )&0xFF));
+	} else {
+		// No cached indexes, use the shapes' bounding box centers as a guess for a starting axis.
+		cpVect axis = cpvperp(cpvsub(cpBBCenter(ctx->shape1->bb), cpBBCenter(ctx->shape2->bb)));
+		v0 = Support(ctx, axis);
+		v1 = Support(ctx, cpvneg(axis));
+	}
+	
+	struct ClosestPoints points = GJKRecurse(ctx, v0, v1, 1);
+	*id = points.id;
+	return points;
+}
+
+//MARK: Contact Clipping
+
+// Given two support edges, find contact point pairs on their surfaces.
+static inline void
+ContactPoints(const struct Edge e1, const struct Edge e2, const struct ClosestPoints points, struct cpCollisionInfo *info)
+{
+	cpFloat mindist = e1.r + e2.r;
+	if(points.d <= mindist){
+#ifdef DRAW_CLIP
+	ChipmunkDebugDrawFatSegment(e1.a.p, e1.b.p, e1.r, RGBAColor(0, 1, 0, 1), LAColor(0, 0));
+	ChipmunkDebugDrawFatSegment(e2.a.p, e2.b.p, e2.r, RGBAColor(1, 0, 0, 1), LAColor(0, 0));
+#endif
+		cpVect n = info->n = points.n;
+		
+		// Distances along the axis parallel to n
+		cpFloat d_e1_a = cpvcross(e1.a.p, n);
+		cpFloat d_e1_b = cpvcross(e1.b.p, n);
+		cpFloat d_e2_a = cpvcross(e2.a.p, n);
+		cpFloat d_e2_b = cpvcross(e2.b.p, n);
+		
+		// TODO + min isn't a complete fix.
+		cpFloat e1_denom = 1.0f/(d_e1_b - d_e1_a + CPFLOAT_MIN);
+		cpFloat e2_denom = 1.0f/(d_e2_b - d_e2_a + CPFLOAT_MIN);
+		
+		// Project the endpoints of the two edges onto the opposing edge, clamping them as necessary.
+		// Compare the projected points to the collision normal to see if the shapes overlap there.
+		{
+			cpVect p1 = cpvadd(cpvmult(n,  e1.r), cpvlerp(e1.a.p, e1.b.p, cpfclamp01((d_e2_b - d_e1_a)*e1_denom)));
+			cpVect p2 = cpvadd(cpvmult(n, -e2.r), cpvlerp(e2.a.p, e2.b.p, cpfclamp01((d_e1_a - d_e2_a)*e2_denom)));
+			cpFloat dist = cpvdot(cpvsub(p2, p1), n);
+			if(dist <= 0.0f){
+				cpHashValue hash_1a2b = CP_HASH_PAIR(e1.a.hash, e2.b.hash);
+				cpCollisionInfoPushContact(info, p1, p2, hash_1a2b);
+			}
+		}{
+			cpVect p1 = cpvadd(cpvmult(n,  e1.r), cpvlerp(e1.a.p, e1.b.p, cpfclamp01((d_e2_a - d_e1_a)*e1_denom)));
+			cpVect p2 = cpvadd(cpvmult(n, -e2.r), cpvlerp(e2.a.p, e2.b.p, cpfclamp01((d_e1_b - d_e2_a)*e2_denom)));
+			cpFloat dist = cpvdot(cpvsub(p2, p1), n);
+			if(dist <= 0.0f){
+				cpHashValue hash_1b2a = CP_HASH_PAIR(e1.b.hash, e2.a.hash);
+				cpCollisionInfoPushContact(info, p1, p2, hash_1b2a);
+			}
+		}
+	}
+}
+
+//MARK: Collision Functions
+
+typedef void (*CollisionFunc)(const cpShape *a, const cpShape *b, struct cpCollisionInfo *info);
+
+// Collide circle shapes.
+static void
+CircleToCircle(const cpCircleShape *c1, const cpCircleShape *c2, struct cpCollisionInfo *info)
+{
+	cpFloat mindist = c1->r + c2->r;
+	cpVect delta = cpvsub(c2->tc, c1->tc);
+	cpFloat distsq = cpvlengthsq(delta);
+	
+	if(distsq < mindist*mindist){
+		cpFloat dist = cpfsqrt(distsq);
+		cpVect n = info->n = (dist ? cpvmult(delta, 1.0f/dist) : cpv(1.0f, 0.0f));
+		cpCollisionInfoPushContact(info, cpvadd(c1->tc, cpvmult(n, c1->r)), cpvadd(c2->tc, cpvmult(n, -c2->r)), 0);
+	}
+}
+
+static void
+CircleToSegment(const cpCircleShape *circle, const cpSegmentShape *segment, struct cpCollisionInfo *info)
+{
+	cpVect seg_a = segment->ta;
+	cpVect seg_b = segment->tb;
+	cpVect center = circle->tc;
+	
+	// Find the closest point on the segment to the circle.
+	cpVect seg_delta = cpvsub(seg_b, seg_a);
+	cpFloat closest_t = cpfclamp01(cpvdot(seg_delta, cpvsub(center, seg_a))/cpvlengthsq(seg_delta));
+	cpVect closest = cpvadd(seg_a, cpvmult(seg_delta, closest_t));
+	
+	// Compare the radii of the two shapes to see if they are colliding.
+	cpFloat mindist = circle->r + segment->r;
+	cpVect delta = cpvsub(closest, center);
+	cpFloat distsq = cpvlengthsq(delta);
+	if(distsq < mindist*mindist){
+		cpFloat dist = cpfsqrt(distsq);
+		// Handle coincident shapes as gracefully as possible.
+		cpVect n = info->n = (dist ? cpvmult(delta, 1.0f/dist) : segment->tn);
+		
+		// Reject endcap collisions if tangents are provided.
+		cpVect rot = cpBodyGetRotation(segment->shape.body);
+		if(
+			(closest_t != 0.0f || cpvdot(n, cpvrotate(segment->a_tangent, rot)) >= 0.0) &&
+			(closest_t != 1.0f || cpvdot(n, cpvrotate(segment->b_tangent, rot)) >= 0.0)
+		){
+			cpCollisionInfoPushContact(info, cpvadd(center, cpvmult(n, circle->r)), cpvadd(closest, cpvmult(n, -segment->r)), 0);
+		}
+	}
+}
+
+static void
+SegmentToSegment(const cpSegmentShape *seg1, const cpSegmentShape *seg2, struct cpCollisionInfo *info)
+{
+	struct SupportContext context = {(cpShape *)seg1, (cpShape *)seg2, (SupportPointFunc)SegmentSupportPoint, (SupportPointFunc)SegmentSupportPoint};
+	struct ClosestPoints points = GJK(&context, &info->id);
+	
+#if DRAW_CLOSEST
+#if PRINT_LOG
+//	ChipmunkDemoPrintString("Distance: %.2f\n", points.d);
+#endif
+	
+	ChipmunkDebugDrawDot(6.0, points.a, RGBAColor(1, 1, 1, 1));
+	ChipmunkDebugDrawDot(6.0, points.b, RGBAColor(1, 1, 1, 1));
+	ChipmunkDebugDrawSegment(points.a, points.b, RGBAColor(1, 1, 1, 1));
+	ChipmunkDebugDrawSegment(points.a, cpvadd(points.a, cpvmult(points.n, 10.0)), RGBAColor(1, 0, 0, 1));
+#endif
+	
+	cpVect n = points.n;
+	cpVect rot1 = cpBodyGetRotation(seg1->shape.body);
+	cpVect rot2 = cpBodyGetRotation(seg2->shape.body);
+	
+	// If the closest points are nearer than the sum of the radii...
+	if(
+		points.d <= (seg1->r + seg2->r) && (
+			// Reject endcap collisions if tangents are provided.
+			(!cpveql(points.a, seg1->ta) || cpvdot(n, cpvrotate(seg1->a_tangent, rot1)) <= 0.0) &&
+			(!cpveql(points.a, seg1->tb) || cpvdot(n, cpvrotate(seg1->b_tangent, rot1)) <= 0.0) &&
+			(!cpveql(points.b, seg2->ta) || cpvdot(n, cpvrotate(seg2->a_tangent, rot2)) >= 0.0) &&
+			(!cpveql(points.b, seg2->tb) || cpvdot(n, cpvrotate(seg2->b_tangent, rot2)) >= 0.0)
+		)
+	){
+		ContactPoints(SupportEdgeForSegment(seg1, n), SupportEdgeForSegment(seg2, cpvneg(n)), points, info);
+	}
+}
+
+static void
+PolyToPoly(const cpPolyShape *poly1, const cpPolyShape *poly2, struct cpCollisionInfo *info)
+{
+	struct SupportContext context = {(cpShape *)poly1, (cpShape *)poly2, (SupportPointFunc)PolySupportPoint, (SupportPointFunc)PolySupportPoint};
+	struct ClosestPoints points = GJK(&context, &info->id);
+	
+#if DRAW_CLOSEST
+#if PRINT_LOG
+//	ChipmunkDemoPrintString("Distance: %.2f\n", points.d);
+#endif
+	
+	ChipmunkDebugDrawDot(3.0, points.a, RGBAColor(1, 1, 1, 1));
+	ChipmunkDebugDrawDot(3.0, points.b, RGBAColor(1, 1, 1, 1));
+	ChipmunkDebugDrawSegment(points.a, points.b, RGBAColor(1, 1, 1, 1));
+	ChipmunkDebugDrawSegment(points.a, cpvadd(points.a, cpvmult(points.n, 10.0)), RGBAColor(1, 0, 0, 1));
+#endif
+	
+	// If the closest points are nearer than the sum of the radii...
+	if(points.d - poly1->r - poly2->r <= 0.0){
+		ContactPoints(SupportEdgeForPoly(poly1, points.n), SupportEdgeForPoly(poly2, cpvneg(points.n)), points, info);
+	}
+}
+
+static void
+SegmentToPoly(const cpSegmentShape *seg, const cpPolyShape *poly, struct cpCollisionInfo *info)
+{
+	struct SupportContext context = {(cpShape *)seg, (cpShape *)poly, (SupportPointFunc)SegmentSupportPoint, (SupportPointFunc)PolySupportPoint};
+	struct ClosestPoints points = GJK(&context, &info->id);
+	
+#if DRAW_CLOSEST
+#if PRINT_LOG
+//	ChipmunkDemoPrintString("Distance: %.2f\n", points.d);
+#endif
+	
+	ChipmunkDebugDrawDot(3.0, points.a, RGBAColor(1, 1, 1, 1));
+	ChipmunkDebugDrawDot(3.0, points.b, RGBAColor(1, 1, 1, 1));
+	ChipmunkDebugDrawSegment(points.a, points.b, RGBAColor(1, 1, 1, 1));
+	ChipmunkDebugDrawSegment(points.a, cpvadd(points.a, cpvmult(points.n, 10.0)), RGBAColor(1, 0, 0, 1));
+#endif
+	
+	cpVect n = points.n;
+	cpVect rot = cpBodyGetRotation(seg->shape.body);
+	
+	if(
+		// If the closest points are nearer than the sum of the radii...
+		points.d - seg->r - poly->r <= 0.0 && (
+			// Reject endcap collisions if tangents are provided.
+			(!cpveql(points.a, seg->ta) || cpvdot(n, cpvrotate(seg->a_tangent, rot)) <= 0.0) &&
+			(!cpveql(points.a, seg->tb) || cpvdot(n, cpvrotate(seg->b_tangent, rot)) <= 0.0)
+		)
+	){
+		ContactPoints(SupportEdgeForSegment(seg, n), SupportEdgeForPoly(poly, cpvneg(n)), points, info);
+	}
+}
+
+static void
+CircleToPoly(const cpCircleShape *circle, const cpPolyShape *poly, struct cpCollisionInfo *info)
+{
+	struct SupportContext context = {(cpShape *)circle, (cpShape *)poly, (SupportPointFunc)CircleSupportPoint, (SupportPointFunc)PolySupportPoint};
+	struct ClosestPoints points = GJK(&context, &info->id);
+	
+#if DRAW_CLOSEST
+	ChipmunkDebugDrawDot(3.0, points.a, RGBAColor(1, 1, 1, 1));
+	ChipmunkDebugDrawDot(3.0, points.b, RGBAColor(1, 1, 1, 1));
+	ChipmunkDebugDrawSegment(points.a, points.b, RGBAColor(1, 1, 1, 1));
+	ChipmunkDebugDrawSegment(points.a, cpvadd(points.a, cpvmult(points.n, 10.0)), RGBAColor(1, 0, 0, 1));
+#endif
+	
+	// If the closest points are nearer than the sum of the radii...
+	if(points.d <= circle->r + poly->r){
+		cpVect n = info->n = points.n;
+		cpCollisionInfoPushContact(info, cpvadd(points.a, cpvmult(n, circle->r)), cpvadd(points.b, cpvmult(n, poly->r)), 0);
+	}
+}
+
+static void
+CollisionError(const cpShape *circle, const cpShape *poly, struct cpCollisionInfo *info)
+{
+	cpAssertHard(cpFalse, "Internal Error: Shape types are not sorted.");
+}
+
+
+static const CollisionFunc BuiltinCollisionFuncs[9] = {
+	(CollisionFunc)CircleToCircle,
+	CollisionError,
+	CollisionError,
+	(CollisionFunc)CircleToSegment,
+	(CollisionFunc)SegmentToSegment,
+	CollisionError,
+	(CollisionFunc)CircleToPoly,
+	(CollisionFunc)SegmentToPoly,
+	(CollisionFunc)PolyToPoly,
+};
+static const CollisionFunc *CollisionFuncs = BuiltinCollisionFuncs;
+
+struct cpCollisionInfo
+cpCollide(const cpShape *a, const cpShape *b, cpCollisionID id, struct cpContact *contacts)
+{
+	struct cpCollisionInfo info = {a, b, id, cpvzero, 0, contacts};
+	
+	// Make sure the shape types are in order.
+	if(a->klass->type > b->klass->type){
+		info.a = b;
+		info.b = a;
+	}
+	
+	CollisionFuncs[info.a->klass->type + info.b->klass->type*CP_NUM_SHAPES](info.a, info.b, &info);
+	
+//	if(0){
+//		for(int i=0; i<info.count; i++){
+//			cpVect r1 = info.arr[i].r1;
+//			cpVect r2 = info.arr[i].r2;
+//			cpVect mid = cpvlerp(r1, r2, 0.5f);
+//			
+//			ChipmunkDebugDrawSegment(r1, mid, RGBAColor(1, 0, 0, 1));
+//			ChipmunkDebugDrawSegment(r2, mid, RGBAColor(0, 0, 1, 1));
+//		}
+//	}
+	
+	return info;
+}
diff --git a/Chipmunk2D-7.0.2/src/cpConstraint.c b/Chipmunk2D-7.0.2/src/cpConstraint.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpConstraint.c
@@ -0,0 +1,173 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+// TODO: Comment me!
+
+void cpConstraintDestroy(cpConstraint *constraint){}
+
+void
+cpConstraintFree(cpConstraint *constraint)
+{
+	if(constraint){
+		cpConstraintDestroy(constraint);
+		cpfree(constraint);
+	}
+}
+
+void
+cpConstraintInit(cpConstraint *constraint, const cpConstraintClass *klass, cpBody *a, cpBody *b)
+{
+	constraint->klass = klass;
+	
+	constraint->a = a;
+	constraint->b = b;
+	constraint->space = NULL;
+	
+	constraint->next_a = NULL;
+	constraint->next_b = NULL;
+	
+	constraint->maxForce = (cpFloat)INFINITY;
+	constraint->errorBias = cpfpow(1.0f - 0.1f, 60.0f);
+	constraint->maxBias = (cpFloat)INFINITY;
+	
+	constraint->collideBodies = cpTrue;
+	
+	constraint->preSolve = NULL;
+	constraint->postSolve = NULL;
+}
+
+cpSpace *
+cpConstraintGetSpace(const cpConstraint *constraint)
+{
+	return constraint->space;
+}
+
+cpBody *
+cpConstraintGetBodyA(const cpConstraint *constraint)
+{
+	return constraint->a;
+}
+
+cpBody *
+cpConstraintGetBodyB(const cpConstraint *constraint)
+{
+	return constraint->b;
+}
+
+cpFloat
+cpConstraintGetMaxForce(const cpConstraint *constraint)
+{
+	return constraint->maxForce;
+}
+
+void
+cpConstraintSetMaxForce(cpConstraint *constraint, cpFloat maxForce)
+{
+	cpAssertHard(maxForce >= 0.0f, "maxForce must be positive.");
+	cpConstraintActivateBodies(constraint);
+	constraint->maxForce = maxForce;
+}
+
+cpFloat
+cpConstraintGetErrorBias(const cpConstraint *constraint)
+{
+	return constraint->errorBias;
+}
+
+void
+cpConstraintSetErrorBias(cpConstraint *constraint, cpFloat errorBias)
+{
+	cpAssertHard(errorBias >= 0.0f, "errorBias must be positive.");
+	cpConstraintActivateBodies(constraint);
+	constraint->errorBias = errorBias;
+}
+
+cpFloat
+cpConstraintGetMaxBias(const cpConstraint *constraint)
+{
+	return constraint->maxBias;
+}
+
+void
+cpConstraintSetMaxBias(cpConstraint *constraint, cpFloat maxBias)
+{
+	cpAssertHard(maxBias >= 0.0f, "maxBias must be positive.");
+	cpConstraintActivateBodies(constraint);
+	constraint->maxBias = maxBias;
+}
+
+cpBool
+cpConstraintGetCollideBodies(const cpConstraint *constraint)
+{
+	return constraint->collideBodies;
+}
+
+void
+cpConstraintSetCollideBodies(cpConstraint *constraint, cpBool collideBodies)
+{
+	cpConstraintActivateBodies(constraint);
+	constraint->collideBodies = collideBodies;
+}
+
+cpConstraintPreSolveFunc
+cpConstraintGetPreSolveFunc(const cpConstraint *constraint)
+{
+	return constraint->preSolve;
+}
+
+void
+cpConstraintSetPreSolveFunc(cpConstraint *constraint, cpConstraintPreSolveFunc preSolveFunc)
+{
+	constraint->preSolve = preSolveFunc;
+}
+
+cpConstraintPostSolveFunc
+cpConstraintGetPostSolveFunc(const cpConstraint *constraint)
+{
+	return constraint->postSolve;
+}
+
+void
+cpConstraintSetPostSolveFunc(cpConstraint *constraint, cpConstraintPostSolveFunc postSolveFunc)
+{
+	constraint->postSolve = postSolveFunc;
+}
+
+cpDataPointer
+cpConstraintGetUserData(const cpConstraint *constraint)
+{
+	return constraint->userData;
+}
+
+void
+cpConstraintSetUserData(cpConstraint *constraint, cpDataPointer userData)
+{
+	constraint->userData = userData;
+}
+
+
+cpFloat
+cpConstraintGetImpulse(cpConstraint *constraint)
+{
+	return constraint->klass->getImpulse(constraint);
+}
diff --git a/Chipmunk2D-7.0.2/src/cpDampedRotarySpring.c b/Chipmunk2D-7.0.2/src/cpDampedRotarySpring.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpDampedRotarySpring.c
@@ -0,0 +1,178 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static cpFloat
+defaultSpringTorque(cpDampedRotarySpring *spring, cpFloat relativeAngle){
+	return (relativeAngle - spring->restAngle)*spring->stiffness;
+}
+
+static void
+preStep(cpDampedRotarySpring *spring, cpFloat dt)
+{
+	cpBody *a = spring->constraint.a;
+	cpBody *b = spring->constraint.b;
+	
+	cpFloat moment = a->i_inv + b->i_inv;
+	cpAssertSoft(moment != 0.0, "Unsolvable spring.");
+	spring->iSum = 1.0f/moment;
+
+	spring->w_coef = 1.0f - cpfexp(-spring->damping*dt*moment);
+	spring->target_wrn = 0.0f;
+
+	// apply spring torque
+	cpFloat j_spring = spring->springTorqueFunc((cpConstraint *)spring, a->a - b->a)*dt;
+	spring->jAcc = j_spring;
+	
+	a->w -= j_spring*a->i_inv;
+	b->w += j_spring*b->i_inv;
+}
+
+static void applyCachedImpulse(cpDampedRotarySpring *spring, cpFloat dt_coef){}
+
+static void
+applyImpulse(cpDampedRotarySpring *spring, cpFloat dt)
+{
+	cpBody *a = spring->constraint.a;
+	cpBody *b = spring->constraint.b;
+	
+	// compute relative velocity
+	cpFloat wrn = a->w - b->w;//normal_relative_velocity(a, b, r1, r2, n) - spring->target_vrn;
+	
+	// compute velocity loss from drag
+	// not 100% certain this is derived correctly, though it makes sense
+	cpFloat w_damp = (spring->target_wrn - wrn)*spring->w_coef;
+	spring->target_wrn = wrn + w_damp;
+	
+	//apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, v_damp*spring->nMass));
+	cpFloat j_damp = w_damp*spring->iSum;
+	spring->jAcc += j_damp;
+	
+	a->w += j_damp*a->i_inv;
+	b->w -= j_damp*b->i_inv;
+}
+
+static cpFloat
+getImpulse(cpDampedRotarySpring *spring)
+{
+	return spring->jAcc;
+}
+
+static const cpConstraintClass klass = {
+	(cpConstraintPreStepImpl)preStep,
+	(cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+	(cpConstraintApplyImpulseImpl)applyImpulse,
+	(cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpDampedRotarySpring *
+cpDampedRotarySpringAlloc(void)
+{
+	return (cpDampedRotarySpring *)cpcalloc(1, sizeof(cpDampedRotarySpring));
+}
+
+cpDampedRotarySpring *
+cpDampedRotarySpringInit(cpDampedRotarySpring *spring, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping)
+{
+	cpConstraintInit((cpConstraint *)spring, &klass, a, b);
+	
+	spring->restAngle = restAngle;
+	spring->stiffness = stiffness;
+	spring->damping = damping;
+	spring->springTorqueFunc = (cpDampedRotarySpringTorqueFunc)defaultSpringTorque;
+	
+	spring->jAcc = 0.0f;
+	
+	return spring;
+}
+
+cpConstraint *
+cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping)
+{
+	return (cpConstraint *)cpDampedRotarySpringInit(cpDampedRotarySpringAlloc(), a, b, restAngle, stiffness, damping);
+}
+
+cpBool
+cpConstraintIsDampedRotarySpring(const cpConstraint *constraint)
+{
+	return (constraint->klass == &klass);
+}
+
+cpFloat
+cpDampedRotarySpringGetRestAngle(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+	return ((cpDampedRotarySpring *)constraint)->restAngle;
+}
+
+void
+cpDampedRotarySpringSetRestAngle(cpConstraint *constraint, cpFloat restAngle)
+{
+	cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+	cpConstraintActivateBodies(constraint);
+	((cpDampedRotarySpring *)constraint)->restAngle = restAngle;
+}
+
+cpFloat
+cpDampedRotarySpringGetStiffness(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+	return ((cpDampedRotarySpring *)constraint)->stiffness;
+}
+
+void
+cpDampedRotarySpringSetStiffness(cpConstraint *constraint, cpFloat stiffness)
+{
+	cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+	cpConstraintActivateBodies(constraint);
+	((cpDampedRotarySpring *)constraint)->stiffness = stiffness;
+}
+
+cpFloat
+cpDampedRotarySpringGetDamping(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+	return ((cpDampedRotarySpring *)constraint)->damping;
+}
+
+void
+cpDampedRotarySpringSetDamping(cpConstraint *constraint, cpFloat damping)
+{
+	cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+	cpConstraintActivateBodies(constraint);
+	((cpDampedRotarySpring *)constraint)->damping = damping;
+}
+
+cpDampedRotarySpringTorqueFunc
+cpDampedRotarySpringGetSpringTorqueFunc(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+	return ((cpDampedRotarySpring *)constraint)->springTorqueFunc;
+}
+
+void
+cpDampedRotarySpringSetSpringTorqueFunc(cpConstraint *constraint, cpDampedRotarySpringTorqueFunc springTorqueFunc)
+{
+	cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+	cpConstraintActivateBodies(constraint);
+	((cpDampedRotarySpring *)constraint)->springTorqueFunc = springTorqueFunc;
+}
diff --git a/Chipmunk2D-7.0.2/src/cpDampedSpring.c b/Chipmunk2D-7.0.2/src/cpDampedSpring.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpDampedSpring.c
@@ -0,0 +1,216 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static cpFloat
+defaultSpringForce(cpDampedSpring *spring, cpFloat dist){
+	return (spring->restLength - dist)*spring->stiffness;
+}
+
+static void
+preStep(cpDampedSpring *spring, cpFloat dt)
+{
+	cpBody *a = spring->constraint.a;
+	cpBody *b = spring->constraint.b;
+	
+	spring->r1 = cpTransformVect(a->transform, cpvsub(spring->anchorA, a->cog));
+	spring->r2 = cpTransformVect(b->transform, cpvsub(spring->anchorB, b->cog));
+	
+	cpVect delta = cpvsub(cpvadd(b->p, spring->r2), cpvadd(a->p, spring->r1));
+	cpFloat dist = cpvlength(delta);
+	spring->n = cpvmult(delta, 1.0f/(dist ? dist : INFINITY));
+	
+	cpFloat k = k_scalar(a, b, spring->r1, spring->r2, spring->n);
+	cpAssertSoft(k != 0.0, "Unsolvable spring.");
+	spring->nMass = 1.0f/k;
+	
+	spring->target_vrn = 0.0f;
+	spring->v_coef = 1.0f - cpfexp(-spring->damping*dt*k);
+
+	// apply spring force
+	cpFloat f_spring = spring->springForceFunc((cpConstraint *)spring, dist);
+	cpFloat j_spring = spring->jAcc = f_spring*dt;
+	apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, j_spring));
+}
+
+static void applyCachedImpulse(cpDampedSpring *spring, cpFloat dt_coef){}
+
+static void
+applyImpulse(cpDampedSpring *spring, cpFloat dt)
+{
+	cpBody *a = spring->constraint.a;
+	cpBody *b = spring->constraint.b;
+	
+	cpVect n = spring->n;
+	cpVect r1 = spring->r1;
+	cpVect r2 = spring->r2;
+
+	// compute relative velocity
+	cpFloat vrn = normal_relative_velocity(a, b, r1, r2, n);
+	
+	// compute velocity loss from drag
+	cpFloat v_damp = (spring->target_vrn - vrn)*spring->v_coef;
+	spring->target_vrn = vrn + v_damp;
+	
+	cpFloat j_damp = v_damp*spring->nMass;
+	spring->jAcc += j_damp;
+	apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, j_damp));
+}
+
+static cpFloat
+getImpulse(cpDampedSpring *spring)
+{
+	return spring->jAcc;
+}
+
+static const cpConstraintClass klass = {
+	(cpConstraintPreStepImpl)preStep,
+	(cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+	(cpConstraintApplyImpulseImpl)applyImpulse,
+	(cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpDampedSpring *
+cpDampedSpringAlloc(void)
+{
+	return (cpDampedSpring *)cpcalloc(1, sizeof(cpDampedSpring));
+}
+
+cpDampedSpring *
+cpDampedSpringInit(cpDampedSpring *spring, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat restLength, cpFloat stiffness, cpFloat damping)
+{
+	cpConstraintInit((cpConstraint *)spring, &klass, a, b);
+	
+	spring->anchorA = anchorA;
+	spring->anchorB = anchorB;
+	
+	spring->restLength = restLength;
+	spring->stiffness = stiffness;
+	spring->damping = damping;
+	spring->springForceFunc = (cpDampedSpringForceFunc)defaultSpringForce;
+	
+	spring->jAcc = 0.0f;
+	
+	return spring;
+}
+
+cpConstraint *
+cpDampedSpringNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat restLength, cpFloat stiffness, cpFloat damping)
+{
+	return (cpConstraint *)cpDampedSpringInit(cpDampedSpringAlloc(), a, b, anchorA, anchorB, restLength, stiffness, damping);
+}
+
+cpBool
+cpConstraintIsDampedSpring(const cpConstraint *constraint)
+{
+	return (constraint->klass == &klass);
+}
+
+cpVect
+cpDampedSpringGetAnchorA(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+	return ((cpDampedSpring *)constraint)->anchorA;
+}
+
+void
+cpDampedSpringSetAnchorA(cpConstraint *constraint, cpVect anchorA)
+{
+	cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+	cpConstraintActivateBodies(constraint);
+	((cpDampedSpring *)constraint)->anchorA = anchorA;
+}
+
+cpVect
+cpDampedSpringGetAnchorB(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+	return ((cpDampedSpring *)constraint)->anchorB;
+}
+
+void
+cpDampedSpringSetAnchorB(cpConstraint *constraint, cpVect anchorB)
+{
+	cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+	cpConstraintActivateBodies(constraint);
+	((cpDampedSpring *)constraint)->anchorB = anchorB;
+}
+
+cpFloat
+cpDampedSpringGetRestLength(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+	return ((cpDampedSpring *)constraint)->restLength;
+}
+
+void
+cpDampedSpringSetRestLength(cpConstraint *constraint, cpFloat restLength)
+{
+	cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+	cpConstraintActivateBodies(constraint);
+	((cpDampedSpring *)constraint)->restLength = restLength;
+}
+
+cpFloat
+cpDampedSpringGetStiffness(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+	return ((cpDampedSpring *)constraint)->stiffness;
+}
+
+void
+cpDampedSpringSetStiffness(cpConstraint *constraint, cpFloat stiffness)
+{
+	cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+	cpConstraintActivateBodies(constraint);
+	((cpDampedSpring *)constraint)->stiffness = stiffness;
+}
+
+cpFloat
+cpDampedSpringGetDamping(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+	return ((cpDampedSpring *)constraint)->damping;
+}
+
+void
+cpDampedSpringSetDamping(cpConstraint *constraint, cpFloat damping)
+{
+	cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+	cpConstraintActivateBodies(constraint);
+	((cpDampedSpring *)constraint)->damping = damping;
+}
+
+cpDampedSpringForceFunc
+cpDampedSpringGetSpringForceFunc(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+	return ((cpDampedSpring *)constraint)->springForceFunc;
+}
+
+void
+cpDampedSpringSetSpringForceFunc(cpConstraint *constraint, cpDampedSpringForceFunc springForceFunc)
+{
+	cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+	cpConstraintActivateBodies(constraint);
+	((cpDampedSpring *)constraint)->springForceFunc = springForceFunc;
+}
diff --git a/Chipmunk2D-7.0.2/src/cpGearJoint.c b/Chipmunk2D-7.0.2/src/cpGearJoint.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpGearJoint.c
@@ -0,0 +1,145 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpGearJoint *joint, cpFloat dt)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	// calculate moment of inertia coefficient.
+	joint->iSum = 1.0f/(a->i_inv*joint->ratio_inv + joint->ratio*b->i_inv);
+	
+	// calculate bias velocity
+	cpFloat maxBias = joint->constraint.maxBias;
+	joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*(b->a*joint->ratio - a->a - joint->phase)/dt, -maxBias, maxBias);
+}
+
+static void
+applyCachedImpulse(cpGearJoint *joint, cpFloat dt_coef)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	cpFloat j = joint->jAcc*dt_coef;
+	a->w -= j*a->i_inv*joint->ratio_inv;
+	b->w += j*b->i_inv;
+}
+
+static void
+applyImpulse(cpGearJoint *joint, cpFloat dt)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	// compute relative rotational velocity
+	cpFloat wr = b->w*joint->ratio - a->w;
+	
+	cpFloat jMax = joint->constraint.maxForce*dt;
+	
+	// compute normal impulse	
+	cpFloat j = (joint->bias - wr)*joint->iSum;
+	cpFloat jOld = joint->jAcc;
+	joint->jAcc = cpfclamp(jOld + j, -jMax, jMax);
+	j = joint->jAcc - jOld;
+	
+	// apply impulse
+	a->w -= j*a->i_inv*joint->ratio_inv;
+	b->w += j*b->i_inv;
+}
+
+static cpFloat
+getImpulse(cpGearJoint *joint)
+{
+	return cpfabs(joint->jAcc);
+}
+
+static const cpConstraintClass klass = {
+	(cpConstraintPreStepImpl)preStep,
+	(cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+	(cpConstraintApplyImpulseImpl)applyImpulse,
+	(cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpGearJoint *
+cpGearJointAlloc(void)
+{
+	return (cpGearJoint *)cpcalloc(1, sizeof(cpGearJoint));
+}
+
+cpGearJoint *
+cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio)
+{
+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+	
+	joint->phase = phase;
+	joint->ratio = ratio;
+	joint->ratio_inv = 1.0f/ratio;
+	
+	joint->jAcc = 0.0f;
+	
+	return joint;
+}
+
+cpConstraint *
+cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio)
+{
+	return (cpConstraint *)cpGearJointInit(cpGearJointAlloc(), a, b, phase, ratio);
+}
+
+cpBool
+cpConstraintIsGearJoint(const cpConstraint *constraint)
+{
+	return (constraint->klass == &klass);
+}
+
+cpFloat
+cpGearJointGetPhase(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsGearJoint(constraint), "Constraint is not a ratchet joint.");
+	return ((cpGearJoint *)constraint)->phase;
+}
+
+void
+cpGearJointSetPhase(cpConstraint *constraint, cpFloat phase)
+{
+	cpAssertHard(cpConstraintIsGearJoint(constraint), "Constraint is not a ratchet joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpGearJoint *)constraint)->phase = phase;
+}
+
+cpFloat
+cpGearJointGetRatio(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsGearJoint(constraint), "Constraint is not a ratchet joint.");
+	return ((cpGearJoint *)constraint)->ratio;
+}
+
+void
+cpGearJointSetRatio(cpConstraint *constraint, cpFloat ratio)
+{
+	cpAssertHard(cpConstraintIsGearJoint(constraint), "Constraint is not a ratchet joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpGearJoint *)constraint)->ratio = ratio;
+	((cpGearJoint *)constraint)->ratio_inv = 1.0f/ratio;
+}
diff --git a/Chipmunk2D-7.0.2/src/cpGrooveJoint.c b/Chipmunk2D-7.0.2/src/cpGrooveJoint.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpGrooveJoint.c
@@ -0,0 +1,197 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpGrooveJoint *joint, cpFloat dt)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	// calculate endpoints in worldspace
+	cpVect ta = cpTransformPoint(a->transform, joint->grv_a);
+	cpVect tb = cpTransformPoint(a->transform, joint->grv_b);
+
+	// calculate axis
+	cpVect n = cpTransformVect(a->transform, joint->grv_n);
+	cpFloat d = cpvdot(ta, n);
+	
+	joint->grv_tn = n;
+	joint->r2 = cpTransformVect(b->transform, cpvsub(joint->anchorB, b->cog));
+	
+	// calculate tangential distance along the axis of r2
+	cpFloat td = cpvcross(cpvadd(b->p, joint->r2), n);
+	// calculate clamping factor and r2
+	if(td <= cpvcross(ta, n)){
+		joint->clamp = 1.0f;
+		joint->r1 = cpvsub(ta, a->p);
+	} else if(td >= cpvcross(tb, n)){
+		joint->clamp = -1.0f;
+		joint->r1 = cpvsub(tb, a->p);
+	} else {
+		joint->clamp = 0.0f;
+		joint->r1 = cpvsub(cpvadd(cpvmult(cpvperp(n), -td), cpvmult(n, d)), a->p);
+	}
+	
+	// Calculate mass tensor
+	joint->k = k_tensor(a, b, joint->r1, joint->r2);
+	
+	// calculate bias velocity
+	cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
+	joint->bias = cpvclamp(cpvmult(delta, -bias_coef(joint->constraint.errorBias, dt)/dt), joint->constraint.maxBias);
+}
+
+static void
+applyCachedImpulse(cpGrooveJoint *joint, cpFloat dt_coef)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+		
+	apply_impulses(a, b, joint->r1, joint->r2, cpvmult(joint->jAcc, dt_coef));
+}
+
+static inline cpVect
+grooveConstrain(cpGrooveJoint *joint, cpVect j, cpFloat dt){
+	cpVect n = joint->grv_tn;
+	cpVect jClamp = (joint->clamp*cpvcross(j, n) > 0.0f) ? j : cpvproject(j, n);
+	return cpvclamp(jClamp, joint->constraint.maxForce*dt);
+}
+
+static void
+applyImpulse(cpGrooveJoint *joint, cpFloat dt)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	cpVect r1 = joint->r1;
+	cpVect r2 = joint->r2;
+	
+	// compute impulse
+	cpVect vr = relative_velocity(a, b, r1, r2);
+
+	cpVect j = cpMat2x2Transform(joint->k, cpvsub(joint->bias, vr));
+	cpVect jOld = joint->jAcc;
+	joint->jAcc = grooveConstrain(joint, cpvadd(jOld, j), dt);
+	j = cpvsub(joint->jAcc, jOld);
+	
+	// apply impulse
+	apply_impulses(a, b, joint->r1, joint->r2, j);
+}
+
+static cpFloat
+getImpulse(cpGrooveJoint *joint)
+{
+	return cpvlength(joint->jAcc);
+}
+
+static const cpConstraintClass klass = {
+	(cpConstraintPreStepImpl)preStep,
+	(cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+	(cpConstraintApplyImpulseImpl)applyImpulse,
+	(cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpGrooveJoint *
+cpGrooveJointAlloc(void)
+{
+	return (cpGrooveJoint *)cpcalloc(1, sizeof(cpGrooveJoint));
+}
+
+cpGrooveJoint *
+cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchorB)
+{
+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+	
+	joint->grv_a = groove_a;
+	joint->grv_b = groove_b;
+	joint->grv_n = cpvperp(cpvnormalize(cpvsub(groove_b, groove_a)));
+	joint->anchorB = anchorB;
+	
+	joint->jAcc = cpvzero;
+	
+	return joint;
+}
+
+cpConstraint *
+cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchorB)
+{
+	return (cpConstraint *)cpGrooveJointInit(cpGrooveJointAlloc(), a, b, groove_a, groove_b, anchorB);
+}
+
+cpBool
+cpConstraintIsGrooveJoint(const cpConstraint *constraint)
+{
+	return (constraint->klass == &klass);
+}
+
+cpVect
+cpGrooveJointGetGrooveA(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint.");
+	return ((cpGrooveJoint *)constraint)->grv_a;
+}
+
+void
+cpGrooveJointSetGrooveA(cpConstraint *constraint, cpVect value)
+{
+	cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint.");
+	cpGrooveJoint *g = (cpGrooveJoint *)constraint;
+	
+	g->grv_a = value;
+	g->grv_n = cpvperp(cpvnormalize(cpvsub(g->grv_b, value)));
+	
+	cpConstraintActivateBodies(constraint);
+}
+
+cpVect
+cpGrooveJointGetGrooveB(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint.");
+	return ((cpGrooveJoint *)constraint)->grv_b;
+}
+
+void
+cpGrooveJointSetGrooveB(cpConstraint *constraint, cpVect value)
+{
+	cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint.");
+	cpGrooveJoint *g = (cpGrooveJoint *)constraint;
+	
+	g->grv_b = value;
+	g->grv_n = cpvperp(cpvnormalize(cpvsub(value, g->grv_a)));
+	
+	cpConstraintActivateBodies(constraint);
+}
+
+cpVect
+cpGrooveJointGetAnchorB(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint.");
+	return ((cpGrooveJoint *)constraint)->anchorB;
+}
+
+void
+cpGrooveJointSetAnchorB(cpConstraint *constraint, cpVect anchorB)
+{
+	cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpGrooveJoint *)constraint)->anchorB = anchorB;
+}
diff --git a/Chipmunk2D-7.0.2/src/cpHashSet.c b/Chipmunk2D-7.0.2/src/cpHashSet.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpHashSet.c
@@ -0,0 +1,253 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+#include "prime.h"
+
+typedef struct cpHashSetBin {
+	void *elt;
+	cpHashValue hash;
+	struct cpHashSetBin *next;
+} cpHashSetBin;
+
+struct cpHashSet {
+	unsigned int entries, size;
+	
+	cpHashSetEqlFunc eql;
+	void *default_value;
+	
+	cpHashSetBin **table;
+	cpHashSetBin *pooledBins;
+	
+	cpArray *allocatedBuffers;
+};
+
+void
+cpHashSetFree(cpHashSet *set)
+{
+	if(set){
+		cpfree(set->table);
+		
+		cpArrayFreeEach(set->allocatedBuffers, cpfree);
+		cpArrayFree(set->allocatedBuffers);
+		
+		cpfree(set);
+	}
+}
+
+cpHashSet *
+cpHashSetNew(int size, cpHashSetEqlFunc eqlFunc)
+{
+	cpHashSet *set = (cpHashSet *)cpcalloc(1, sizeof(cpHashSet));
+	
+	set->size = next_prime(size);
+	set->entries = 0;
+	
+	set->eql = eqlFunc;
+	set->default_value = NULL;
+	
+	set->table = (cpHashSetBin **)cpcalloc(set->size, sizeof(cpHashSetBin *));
+	set->pooledBins = NULL;
+	
+	set->allocatedBuffers = cpArrayNew(0);
+	
+	return set;
+}
+
+void
+cpHashSetSetDefaultValue(cpHashSet *set, void *default_value)
+{
+	set->default_value = default_value;
+}
+
+static int
+setIsFull(cpHashSet *set)
+{
+	return (set->entries >= set->size);
+}
+
+static void
+cpHashSetResize(cpHashSet *set)
+{
+	// Get the next approximate doubled prime.
+	unsigned int newSize = next_prime(set->size + 1);
+	// Allocate a new table.
+	cpHashSetBin **newTable = (cpHashSetBin **)cpcalloc(newSize, sizeof(cpHashSetBin *));
+	
+	// Iterate over the chains.
+	for(unsigned int i=0; i<set->size; i++){
+		// Rehash the bins into the new table.
+		cpHashSetBin *bin = set->table[i];
+		while(bin){
+			cpHashSetBin *next = bin->next;
+			
+			cpHashValue idx = bin->hash%newSize;
+			bin->next = newTable[idx];
+			newTable[idx] = bin;
+			
+			bin = next;
+		}
+	}
+	
+	cpfree(set->table);
+	
+	set->table = newTable;
+	set->size = newSize;
+}
+
+static inline void
+recycleBin(cpHashSet *set, cpHashSetBin *bin)
+{
+	bin->next = set->pooledBins;
+	set->pooledBins = bin;
+	bin->elt = NULL;
+}
+
+static cpHashSetBin *
+getUnusedBin(cpHashSet *set)
+{
+	cpHashSetBin *bin = set->pooledBins;
+	
+	if(bin){
+		set->pooledBins = bin->next;
+		return bin;
+	} else {
+		// Pool is exhausted, make more
+		int count = CP_BUFFER_BYTES/sizeof(cpHashSetBin);
+		cpAssertHard(count, "Internal Error: Buffer size is too small.");
+		
+		cpHashSetBin *buffer = (cpHashSetBin *)cpcalloc(1, CP_BUFFER_BYTES);
+		cpArrayPush(set->allocatedBuffers, buffer);
+		
+		// push all but the first one, return it instead
+		for(int i=1; i<count; i++) recycleBin(set, buffer + i);
+		return buffer;
+	}
+}
+
+int
+cpHashSetCount(cpHashSet *set)
+{
+	return set->entries;
+}
+
+void *
+cpHashSetInsert(cpHashSet *set, cpHashValue hash, void *ptr, cpHashSetTransFunc trans, void *data)
+{
+	cpHashValue idx = hash%set->size;
+	
+	// Find the bin with the matching element.
+	cpHashSetBin *bin = set->table[idx];
+	while(bin && !set->eql(ptr, bin->elt))
+		bin = bin->next;
+	
+	// Create it if necessary.
+	if(!bin){
+		bin = getUnusedBin(set);
+		bin->hash = hash;
+		bin->elt = (trans ? trans(ptr, data) : data);
+		
+		bin->next = set->table[idx];
+		set->table[idx] = bin;
+		
+		set->entries++;
+		if(setIsFull(set)) cpHashSetResize(set);
+	}
+	
+	return bin->elt;
+}
+
+void *
+cpHashSetRemove(cpHashSet *set, cpHashValue hash, void *ptr)
+{
+	cpHashValue idx = hash%set->size;
+	
+	cpHashSetBin **prev_ptr = &set->table[idx];
+	cpHashSetBin *bin = set->table[idx];
+	
+	// Find the bin
+	while(bin && !set->eql(ptr, bin->elt)){
+		prev_ptr = &bin->next;
+		bin = bin->next;
+	}
+	
+	// Remove it if it exists.
+	if(bin){
+		// Update the previous linked list pointer
+		(*prev_ptr) = bin->next;
+		set->entries--;
+		
+		void *elt = bin->elt;
+		recycleBin(set, bin);
+		
+		return elt;
+	}
+	
+	return NULL;
+}
+
+void *
+cpHashSetFind(cpHashSet *set, cpHashValue hash, void *ptr)
+{	
+	cpHashValue idx = hash%set->size;
+	cpHashSetBin *bin = set->table[idx];
+	while(bin && !set->eql(ptr, bin->elt))
+		bin = bin->next;
+		
+	return (bin ? bin->elt : set->default_value);
+}
+
+void
+cpHashSetEach(cpHashSet *set, cpHashSetIteratorFunc func, void *data)
+{
+	for(unsigned int i=0; i<set->size; i++){
+		cpHashSetBin *bin = set->table[i];
+		while(bin){
+			cpHashSetBin *next = bin->next;
+			func(bin->elt, data);
+			bin = next;
+		}
+	}
+}
+
+void
+cpHashSetFilter(cpHashSet *set, cpHashSetFilterFunc func, void *data)
+{
+	for(unsigned int i=0; i<set->size; i++){
+		// The rest works similarly to cpHashSetRemove() above.
+		cpHashSetBin **prev_ptr = &set->table[i];
+		cpHashSetBin *bin = set->table[i];
+		while(bin){
+			cpHashSetBin *next = bin->next;
+			
+			if(func(bin->elt, data)){
+				prev_ptr = &bin->next;
+			} else {
+				(*prev_ptr) = next;
+
+				set->entries--;
+				recycleBin(set, bin);
+			}
+			
+			bin = next;
+		}
+	}
+}
diff --git a/Chipmunk2D-7.0.2/src/cpHastySpace.c b/Chipmunk2D-7.0.2/src/cpHastySpace.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpHastySpace.c
@@ -0,0 +1,694 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+#include <stdlib.h>
+#include <stdio.h>
+
+//TODO: Move all the thread stuff to another file
+
+//#include <sys/param.h >
+#ifndef _WIN32
+#include <sys/sysctl.h>
+#include <pthread.h>
+#else
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+
+#include <process.h> // _beginthreadex
+#include <windows.h>
+
+#ifndef ETIMEDOUT
+#define ETIMEDOUT 1
+#endif
+
+// Simple pthread implementation for Windows
+// Made from scratch to avoid the LGPL licence from pthread-win32
+enum {
+	SIGNAL = 0,
+	BROADCAST = 1,
+	MAX_EVENTS = 2
+};
+
+typedef HANDLE pthread_t;
+typedef struct
+{
+	// Based on http://www.cs.wustl.edu/~schmidt/win32-cv-1.html since Windows has no condition variable until NT6
+	UINT waiters_count;
+	// Count of the number of waiters.
+
+	CRITICAL_SECTION waiters_count_lock;
+	// Serialize access to <waiters_count_>.
+
+	HANDLE events[MAX_EVENTS];
+} pthread_cond_t;
+typedef CRITICAL_SECTION pthread_mutex_t;
+
+typedef struct {} pthread_condattr_t; // Dummy;
+
+int pthread_cond_destroy(pthread_cond_t* cv)
+{
+	CloseHandle(cv->events[BROADCAST]);
+	CloseHandle(cv->events[SIGNAL]);
+
+	DeleteCriticalSection(&cv->waiters_count_lock);
+
+	return 0;
+}
+
+int pthread_cond_init(pthread_cond_t* cv, const pthread_condattr_t* attr)
+{
+	// Initialize the count to 0.
+	cv->waiters_count = 0;
+
+	// Create an auto-reset event.
+	cv->events[SIGNAL] = CreateEvent(NULL,  // no security
+	                                 FALSE, // auto-reset event
+	                                 FALSE, // non-signaled initially
+	                                 NULL); // unnamed
+
+	// Create a manual-reset event.
+	cv->events[BROADCAST] = CreateEvent(NULL,  // no security
+	                                    TRUE,  // manual-reset
+	                                    FALSE, // non-signaled initially
+	                                    NULL); // unnamed
+
+	InitializeCriticalSection(&cv->waiters_count_lock);
+
+	return 0;
+}
+
+int pthread_cond_broadcast(pthread_cond_t *cv)
+{
+	// Avoid race conditions.
+	EnterCriticalSection(&cv->waiters_count_lock);
+	int have_waiters = cv->waiters_count > 0;
+	LeaveCriticalSection(&cv->waiters_count_lock);
+
+	if (have_waiters)
+		SetEvent(cv->events[BROADCAST]);
+
+	return 0;
+}
+
+int pthread_cond_signal(pthread_cond_t* cv)
+{
+	// Avoid race conditions.
+	EnterCriticalSection(&cv->waiters_count_lock);
+	int have_waiters = cv->waiters_count > 0;
+	LeaveCriticalSection(&cv->waiters_count_lock);
+
+	if (have_waiters)
+		SetEvent(cv->events[SIGNAL]);
+
+	return 0;
+}
+
+int pthread_cond_wait(pthread_cond_t* cv, pthread_mutex_t* external_mutex)
+{
+	// Avoid race conditions.
+	EnterCriticalSection(&cv->waiters_count_lock);
+	cv->waiters_count++;
+	LeaveCriticalSection(&cv->waiters_count_lock);
+
+	// It's ok to release the <external_mutex> here since Win32
+	// manual-reset events maintain state when used with
+	// <SetEvent>.  This avoids the "lost wakeup" bug...
+	LeaveCriticalSection(external_mutex);
+
+	// Wait for either event to become signaled due to <pthread_cond_signal>
+	// being called or <pthread_cond_broadcast> being called.
+	int result = WaitForMultipleObjects(2, cv->events, FALSE, INFINITE);
+
+	EnterCriticalSection(&cv->waiters_count_lock);
+	cv->waiters_count--;
+	int last_waiter =
+		result == WAIT_OBJECT_0 + BROADCAST
+		&& cv->waiters_count == 0;
+	LeaveCriticalSection(&cv->waiters_count_lock);
+
+	// Some thread called <pthread_cond_broadcast>.
+	if (last_waiter)
+		// We're the last waiter to be notified or to stop waiting, so
+		// reset the manual event. 
+		ResetEvent(cv->events[BROADCAST]);
+
+	// Reacquire the <external_mutex>.
+	EnterCriticalSection(external_mutex);
+
+	return result == WAIT_TIMEOUT ? ETIMEDOUT : 0;
+}
+
+typedef struct {} pthread_mutexattr_t; //< Dummy
+
+int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr)
+{
+	InitializeCriticalSection(mutex);
+	return 0;
+}
+
+int pthread_mutex_destroy(pthread_mutex_t* mutex)
+{
+	DeleteCriticalSection(mutex);
+	return 0;
+}
+
+int pthread_mutex_lock(pthread_mutex_t* mutex)
+{
+	EnterCriticalSection(mutex);
+	return 0;
+}
+
+int pthread_mutex_unlock(pthread_mutex_t* mutex)
+{
+	LeaveCriticalSection(mutex);
+	return 0;
+}
+
+typedef struct {} pthread_attr_t;
+
+typedef struct
+{
+	void *(*start_routine) (void *);
+	void* arg;
+} pthread_internal_thread;
+
+unsigned int __stdcall ThreadProc(void* userdata)
+{
+	pthread_internal_thread* ud = (pthread_internal_thread*) userdata;
+	ud->start_routine(ud->arg);
+
+	free(ud);
+
+	return 0;
+}
+
+int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void *(*start_routine) (void *), void *arg)
+{
+	pthread_internal_thread* ud = (pthread_internal_thread*) malloc(sizeof(pthread_internal_thread));
+	ud->start_routine = start_routine;
+	ud->arg = arg;
+
+	*thread = (HANDLE) (_beginthreadex(NULL, 0, &ThreadProc, ud, 0, NULL));
+	if (!*thread)
+		return 1;
+
+	return 0;
+}
+
+int pthread_join(pthread_t thread, void **value_ptr)
+{
+	WaitForSingleObject(thread, INFINITE);
+	CloseHandle(thread);
+
+	return 0;
+}
+
+#endif
+
+#include "chipmunk/chipmunk_private.h"
+#include "chipmunk/cpHastySpace.h"
+
+
+//MARK: ARM NEON Solver
+
+#if __ARM_NEON__
+#include <arm_neon.h>
+
+// Tested and known to work fine with Clang 3.0 and GCC 4.2
+// Doesn't work with Clang 1.6, and I have no idea why.
+#if defined(__clang_major__) && __clang_major__ < 3
+	#error Compiler not supported.
+#endif
+
+#if CP_USE_DOUBLES
+	#if !__arm64
+		#error Cannot use CP_USE_DOUBLES on 32 bit ARM.
+	#endif
+	
+	typedef float64_t cpFloat_t;
+	typedef float64x2_t cpFloatx2_t;
+	#define vld vld1q_f64
+	#define vdup_n vdupq_n_f64
+	#define vst vst1q_f64
+	#define vst_lane vst1q_lane_f64
+	#define vadd vaddq_f64
+	#define vsub vsubq_f64
+	#define vpadd vpaddq_f64
+	#define vmul vmulq_f64
+	#define vmul_n vmulq_n_f64
+	#define vneg vnegq_f64
+	#define vget_lane vgetq_lane_f64
+	#define vset_lane vsetq_lane_f64
+	#define vmin vminq_f64
+	#define vmax vmaxq_f64
+	#define vrev(__a) __builtin_shufflevector(__a, __a, 1, 0)
+#else
+	typedef float32_t cpFloat_t;
+	typedef float32x2_t cpFloatx2_t;
+	#define vld vld1_f32
+	#define vdup_n vdup_n_f32
+	#define vst vst1_f32
+	#define vst_lane vst1_lane_f32
+	#define vadd vadd_f32
+	#define vsub vsub_f32
+	#define vpadd vpadd_f32
+	#define vmul vmul_f32
+	#define vmul_n vmul_n_f32
+	#define vneg vneg_f32
+	#define vget_lane vget_lane_f32
+	#define vset_lane vset_lane_f32
+	#define vmin vmin_f32
+	#define vmax vmax_f32
+	#define vrev vrev64_f32
+#endif
+
+// TODO could probably do better here, maybe using vcreate?
+// especially for the constants
+// Maybe use the {} notation for GCC/Clang?
+static inline cpFloatx2_t
+vmake(cpFloat_t x, cpFloat_t y)
+{
+//	cpFloatx2_t v = {};
+//	v = vset_lane(x, v, 0);
+//	v = vset_lane(y, v, 1);
+//	
+//	return v;
+	
+	// This might not be super compatible, but all the NEON headers use it...
+	return (cpFloatx2_t){x, y};
+}
+
+static void
+cpArbiterApplyImpulse_NEON(cpArbiter *arb)
+{
+	cpBody *a = arb->body_a;
+	cpBody *b = arb->body_b;
+	cpFloatx2_t surface_vr = vld((cpFloat_t *)&arb->surface_vr);
+	cpFloatx2_t n = vld((cpFloat_t *)&arb->n);
+	cpFloat_t friction = arb->u;
+	
+	int numContacts = arb->count;
+	struct cpContact *contacts = arb->contacts;
+	for(int i=0; i<numContacts; i++){
+		struct cpContact *con = contacts + i;
+		cpFloatx2_t r1 = vld((cpFloat_t *)&con->r1);
+		cpFloatx2_t r2 = vld((cpFloat_t *)&con->r2);
+		
+		cpFloatx2_t perp = vmake(-1.0, 1.0);
+		cpFloatx2_t r1p = vmul(vrev(r1), perp);
+		cpFloatx2_t r2p = vmul(vrev(r2), perp);
+		
+		cpFloatx2_t vBias_a = vld((cpFloat_t *)&a->v_bias);
+		cpFloatx2_t vBias_b = vld((cpFloat_t *)&b->v_bias);
+		cpFloatx2_t wBias = vmake(a->w_bias, b->w_bias);
+		
+		cpFloatx2_t vb1 = vadd(vBias_a, vmul_n(r1p, vget_lane(wBias, 0)));
+		cpFloatx2_t vb2 = vadd(vBias_b, vmul_n(r2p, vget_lane(wBias, 1)));
+		cpFloatx2_t vbr = vsub(vb2, vb1);
+		
+		cpFloatx2_t v_a = vld((cpFloat_t *)&a->v);
+		cpFloatx2_t v_b = vld((cpFloat_t *)&b->v);
+		cpFloatx2_t w = vmake(a->w, b->w);
+		cpFloatx2_t v1 = vadd(v_a, vmul_n(r1p, vget_lane(w, 0)));
+		cpFloatx2_t v2 = vadd(v_b, vmul_n(r2p, vget_lane(w, 1)));
+		cpFloatx2_t vr = vsub(v2, v1);
+		
+		cpFloatx2_t vbn_vrn = vpadd(vmul(vbr, n), vmul(vr, n));
+		
+		cpFloatx2_t v_offset = vmake(con->bias, -con->bounce);
+		cpFloatx2_t jOld = vmake(con->jBias, con->jnAcc);
+		cpFloatx2_t jbn_jn = vmul_n(vsub(v_offset, vbn_vrn), con->nMass);
+		jbn_jn = vmax(vadd(jOld, jbn_jn), vdup_n(0.0));
+		cpFloatx2_t jApply = vsub(jbn_jn, jOld);
+		
+		cpFloatx2_t t = vmul(vrev(n), perp);
+		cpFloatx2_t vrt_tmp = vmul(vadd(vr, surface_vr), t);
+		cpFloatx2_t vrt = vpadd(vrt_tmp, vrt_tmp);
+		
+		cpFloatx2_t jtOld = {}; jtOld = vset_lane(con->jtAcc, jtOld, 0);
+		cpFloatx2_t jtMax = vrev(vmul_n(jbn_jn, friction));
+		cpFloatx2_t jt = vmul_n(vrt, -con->tMass);
+		jt = vmax(vneg(jtMax), vmin(vadd(jtOld, jt), jtMax));
+		cpFloatx2_t jtApply = vsub(jt, jtOld);
+		
+		cpFloatx2_t i_inv = vmake(-a->i_inv, b->i_inv);
+		cpFloatx2_t nperp = vmake(1.0, -1.0);
+		
+		cpFloatx2_t jBias = vmul_n(n, vget_lane(jApply, 0));
+		cpFloatx2_t jBiasCross = vmul(vrev(jBias), nperp);
+		cpFloatx2_t biasCrosses = vpadd(vmul(r1, jBiasCross), vmul(r2, jBiasCross));
+		wBias = vadd(wBias, vmul(i_inv, biasCrosses));
+		
+		vBias_a = vsub(vBias_a, vmul_n(jBias, a->m_inv));
+		vBias_b = vadd(vBias_b, vmul_n(jBias, b->m_inv));
+		
+		cpFloatx2_t j = vadd(vmul_n(n, vget_lane(jApply, 1)), vmul_n(t, vget_lane(jtApply, 0)));
+		cpFloatx2_t jCross = vmul(vrev(j), nperp);
+		cpFloatx2_t crosses = vpadd(vmul(r1, jCross), vmul(r2, jCross));
+		w = vadd(w, vmul(i_inv, crosses));
+		
+		v_a = vsub(v_a, vmul_n(j, a->m_inv));
+		v_b = vadd(v_b, vmul_n(j, b->m_inv));
+		
+		// TODO would moving these earlier help pipeline them better?
+		vst((cpFloat_t *)&a->v_bias, vBias_a);
+		vst((cpFloat_t *)&b->v_bias, vBias_b);
+		vst_lane((cpFloat_t *)&a->w_bias, wBias, 0);
+		vst_lane((cpFloat_t *)&b->w_bias, wBias, 1);
+		
+		vst((cpFloat_t *)&a->v, v_a);
+		vst((cpFloat_t *)&b->v, v_b);
+		vst_lane((cpFloat_t *)&a->w, w, 0);
+		vst_lane((cpFloat_t *)&b->w, w, 1);
+		
+		vst_lane((cpFloat_t *)&con->jBias, jbn_jn, 0);
+		vst_lane((cpFloat_t *)&con->jnAcc, jbn_jn, 1);
+		vst_lane((cpFloat_t *)&con->jtAcc, jt, 0);
+	}
+}
+
+#endif
+
+//MARK: PThreads
+
+// Right now using more than 2 threads probably wont help your performance any.
+// If you are using a ridiculous number of iterations it could help though.
+#define MAX_THREADS 2
+
+struct ThreadContext {
+	pthread_t thread;
+	cpHastySpace *space;
+	unsigned long thread_num;
+};
+
+typedef	void (*cpHastySpaceWorkFunction)(cpSpace *space, unsigned long worker, unsigned long worker_count);
+
+struct cpHastySpace {
+	cpSpace space;
+	
+	// Number of worker threads (including the main thread)
+	unsigned long num_threads;
+	
+	// Number of worker threads currently executing. (also including the main thread)
+	unsigned long num_working;
+	
+	// Number of constraints (plus contacts) that must exist per step to start the worker threads.
+	unsigned long constraint_count_threshold;
+	
+	pthread_mutex_t mutex;
+	pthread_cond_t cond_work, cond_resume;
+	
+	// Work function to invoke.
+	cpHastySpaceWorkFunction work;
+	
+	struct ThreadContext workers[MAX_THREADS - 1];
+};
+
+static void *
+WorkerThreadLoop(struct ThreadContext *context)
+{
+	cpHastySpace *hasty = context->space;
+	
+	unsigned long thread = context->thread_num;
+	unsigned long num_threads = hasty->num_threads;
+	
+	for(;;){
+		pthread_mutex_lock(&hasty->mutex); {
+			if(--hasty->num_working == 0){
+				pthread_cond_signal(&hasty->cond_resume);
+			}
+			
+			pthread_cond_wait(&hasty->cond_work, &hasty->mutex);
+		} pthread_mutex_unlock(&hasty->mutex);
+		
+		cpHastySpaceWorkFunction func = hasty->work;
+		if(func){
+			hasty->work(&hasty->space, thread, num_threads);
+		} else {
+			break;
+		}
+	}
+	
+	return NULL;
+}
+
+static void
+RunWorkers(cpHastySpace *hasty, cpHastySpaceWorkFunction func)
+{
+	hasty->num_working = hasty->num_threads - 1;
+	hasty->work = func;
+	
+	if(hasty->num_working > 0){
+		pthread_mutex_lock(&hasty->mutex); {
+			pthread_cond_broadcast(&hasty->cond_work);
+		} pthread_mutex_unlock(&hasty->mutex);
+		
+		func((cpSpace *)hasty, 0, hasty->num_threads);
+			
+		pthread_mutex_lock(&hasty->mutex); {
+			if(hasty->num_working > 0){
+				pthread_cond_wait(&hasty->cond_resume, &hasty->mutex);
+			}
+		} pthread_mutex_unlock(&hasty->mutex);
+	} else {
+		func((cpSpace *)hasty, 0, hasty->num_threads);
+	}
+	
+	hasty->work = NULL;
+}
+
+static void
+Solver(cpSpace *space, unsigned long worker, unsigned long worker_count)
+{
+	cpArray *constraints = space->constraints;
+	cpArray *arbiters = space->arbiters;
+	
+	cpFloat dt = space->curr_dt;
+	unsigned long iterations = (space->iterations + worker_count - 1)/worker_count;
+	
+	for(unsigned long i=0; i<iterations; i++){
+		for(int j=0; j<arbiters->num; j++){
+			cpArbiter *arb = (cpArbiter *)arbiters->arr[j];
+			#ifdef __ARM_NEON__
+				cpArbiterApplyImpulse_NEON(arb);
+			#else
+				cpArbiterApplyImpulse(arb);
+			#endif
+		}
+			
+		for(int j=0; j<constraints->num; j++){
+			cpConstraint *constraint = (cpConstraint *)constraints->arr[j];
+			constraint->klass->applyImpulse(constraint, dt);
+		}
+	}
+}
+
+//MARK: Thread Management Functions
+
+static void
+HaltThreads(cpHastySpace *hasty)
+{
+	pthread_mutex_t *mutex = &hasty->mutex;
+	pthread_mutex_lock(mutex); {
+		hasty->work = NULL; // NULL work function means break and exit
+		pthread_cond_broadcast(&hasty->cond_work);
+	} pthread_mutex_unlock(mutex);
+	
+	for(unsigned long i=0; i<(hasty->num_threads-1); i++){
+		pthread_join(hasty->workers[i].thread, NULL);
+	}
+}
+
+void
+cpHastySpaceSetThreads(cpSpace *space, unsigned long threads)
+{
+#if TARGET_IPHONE_SIMULATOR == 1
+	// Individual values appear to be written non-atomically when compiled as debug for the simulator.
+	// No idea why, so threads are disabled.
+	threads = 1;
+#endif	
+	
+	cpHastySpace *hasty = (cpHastySpace *)space;
+	HaltThreads(hasty);
+	
+#ifdef __APPLE__
+	if(threads == 0){
+		size_t size = sizeof(threads);
+		sysctlbyname("hw.ncpu", &threads, &size, NULL, 0);
+	}
+#else
+	if(threads == 0) threads = 1;
+#endif
+	
+	hasty->num_threads = (threads < MAX_THREADS ? threads : MAX_THREADS);
+	hasty->num_working = hasty->num_threads - 1;
+	
+	// Create the worker threads and wait for them to signal ready.
+	if(hasty->num_working > 0){
+		pthread_mutex_lock(&hasty->mutex);
+		for(unsigned long i=0; i<(hasty->num_threads-1); i++){
+			hasty->workers[i].space = hasty;
+			hasty->workers[i].thread_num = i + 1;
+			
+			pthread_create(&hasty->workers[i].thread, NULL, (void*(*)(void*))WorkerThreadLoop, &hasty->workers[i]);
+		}
+		
+		pthread_cond_wait(&hasty->cond_resume, &hasty->mutex);
+		pthread_mutex_unlock(&hasty->mutex);
+	}
+}
+
+unsigned long
+cpHastySpaceGetThreads(cpSpace *space)
+{
+	return ((cpHastySpace *)space)->num_threads;
+}
+
+//MARK: Overriden cpSpace Functions.
+
+cpSpace *
+cpHastySpaceNew(void)
+{
+	cpHastySpace *hasty = (cpHastySpace *)cpcalloc(1, sizeof(cpHastySpace));
+	cpSpaceInit((cpSpace *)hasty);
+	
+	pthread_mutex_init(&hasty->mutex, NULL);
+	pthread_cond_init(&hasty->cond_work, NULL);
+	pthread_cond_init(&hasty->cond_resume, NULL);
+	
+	// TODO magic number, should test this more thoroughly.
+	hasty->constraint_count_threshold = 50;
+	
+	// Default to 1 thread for determinism.
+	hasty->num_threads = 1;
+	cpHastySpaceSetThreads((cpSpace *)hasty, 1);
+
+	return (cpSpace *)hasty;
+}
+
+void
+cpHastySpaceFree(cpSpace *space)
+{
+	cpHastySpace *hasty = (cpHastySpace *)space;
+	
+	HaltThreads(hasty);
+	
+	pthread_mutex_destroy(&hasty->mutex);
+	pthread_cond_destroy(&hasty->cond_work);
+	pthread_cond_destroy(&hasty->cond_resume);
+	
+	cpSpaceFree(space);
+}
+
+void
+cpHastySpaceStep(cpSpace *space, cpFloat dt)
+{
+	// don't step if the timestep is 0!
+	if(dt == 0.0f) return;
+	
+	space->stamp++;
+	
+	cpFloat prev_dt = space->curr_dt;
+	space->curr_dt = dt;
+		
+	cpArray *bodies = space->dynamicBodies;
+	cpArray *constraints = space->constraints;
+	cpArray *arbiters = space->arbiters;
+	
+	// Reset and empty the arbiter list.
+	for(int i=0; i<arbiters->num; i++){
+		cpArbiter *arb = (cpArbiter *)arbiters->arr[i];
+		arb->state = CP_ARBITER_STATE_NORMAL;
+		
+		// If both bodies are awake, unthread the arbiter from the contact graph.
+		if(!cpBodyIsSleeping(arb->body_a) && !cpBodyIsSleeping(arb->body_b)){
+			cpArbiterUnthread(arb);
+		}
+	}
+	arbiters->num = 0;
+	
+	cpSpaceLock(space); {
+		// Integrate positions
+		for(int i=0; i<bodies->num; i++){
+			cpBody *body = (cpBody *)bodies->arr[i];
+			body->position_func(body, dt);
+		}
+		
+		// Find colliding pairs.
+		cpSpacePushFreshContactBuffer(space);
+		cpSpatialIndexEach(space->dynamicShapes, (cpSpatialIndexIteratorFunc)cpShapeUpdateFunc, NULL);
+		cpSpatialIndexReindexQuery(space->dynamicShapes, (cpSpatialIndexQueryFunc)cpSpaceCollideShapes, space);
+	} cpSpaceUnlock(space, cpFalse);
+	
+	// Rebuild the contact graph (and detect sleeping components if sleeping is enabled)
+	cpSpaceProcessComponents(space, dt);
+	
+	cpSpaceLock(space); {
+		// Clear out old cached arbiters and call separate callbacks
+		cpHashSetFilter(space->cachedArbiters, (cpHashSetFilterFunc)cpSpaceArbiterSetFilter, space);
+
+		// Prestep the arbiters and constraints.
+		cpFloat slop = space->collisionSlop;
+		cpFloat biasCoef = 1.0f - cpfpow(space->collisionBias, dt);
+		for(int i=0; i<arbiters->num; i++){
+			cpArbiterPreStep((cpArbiter *)arbiters->arr[i], dt, slop, biasCoef);
+		}
+
+		for(int i=0; i<constraints->num; i++){
+			cpConstraint *constraint = (cpConstraint *)constraints->arr[i];
+			
+			cpConstraintPreSolveFunc preSolve = constraint->preSolve;
+			if(preSolve) preSolve(constraint, space);
+			
+			constraint->klass->preStep(constraint, dt);
+		}
+	
+		// Integrate velocities.
+		cpFloat damping = cpfpow(space->damping, dt);
+		cpVect gravity = space->gravity;
+		for(int i=0; i<bodies->num; i++){
+			cpBody *body = (cpBody *)bodies->arr[i];
+			body->velocity_func(body, gravity, damping, dt);
+		}
+		
+		// Apply cached impulses
+		cpFloat dt_coef = (prev_dt == 0.0f ? 0.0f : dt/prev_dt);
+		for(int i=0; i<arbiters->num; i++){
+			cpArbiterApplyCachedImpulse((cpArbiter *)arbiters->arr[i], dt_coef);
+		}
+		
+		for(int i=0; i<constraints->num; i++){
+			cpConstraint *constraint = (cpConstraint *)constraints->arr[i];
+			constraint->klass->applyCachedImpulse(constraint, dt_coef);
+		}
+		
+		// Run the impulse solver.
+		cpHastySpace *hasty = (cpHastySpace *)space;
+		if((unsigned long)(arbiters->num + constraints->num) > hasty->constraint_count_threshold){
+			RunWorkers(hasty, Solver);
+		} else {
+			Solver(space, 0, 1);
+		}
+		
+		// Run the constraint post-solve callbacks
+		for(int i=0; i<constraints->num; i++){
+			cpConstraint *constraint = (cpConstraint *)constraints->arr[i];
+			
+			cpConstraintPostSolveFunc postSolve = constraint->postSolve;
+			if(postSolve) postSolve(constraint, space);
+		}
+		
+		// run the post-solve callbacks
+		for(int i=0; i<arbiters->num; i++){
+			cpArbiter *arb = (cpArbiter *) arbiters->arr[i];
+			
+			cpCollisionHandler *handler = arb->handler;
+			handler->postSolveFunc(arb, space, handler->userData);
+		}
+	} cpSpaceUnlock(space, cpTrue);
+}
diff --git a/Chipmunk2D-7.0.2/src/cpMarch.c b/Chipmunk2D-7.0.2/src/cpMarch.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpMarch.c
@@ -0,0 +1,157 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "chipmunk/chipmunk.h"
+#include "chipmunk/cpMarch.h"
+
+
+typedef void (*cpMarchCellFunc)(
+	cpFloat t, cpFloat a, cpFloat b, cpFloat c, cpFloat d,
+	cpFloat x0, cpFloat x1, cpFloat y0, cpFloat y1,
+	cpMarchSegmentFunc segment, void *segment_data
+);
+
+// The looping and sample caching code is shared between cpMarchHard() and cpMarchSoft().
+static void
+cpMarchCells(
+  cpBB bb, unsigned long x_samples, unsigned long y_samples, cpFloat t,
+  cpMarchSegmentFunc segment, void *segment_data,
+  cpMarchSampleFunc sample, void *sample_data,
+	cpMarchCellFunc cell
+){
+	cpFloat x_denom = 1.0/(cpFloat)(x_samples - 1);
+	cpFloat y_denom = 1.0/(cpFloat)(y_samples - 1);
+	
+	// TODO range assertions and short circuit for 0 sized windows.
+	
+	// Keep a copy of the previous row to avoid double lookups.
+	cpFloat *buffer = (cpFloat *)cpcalloc(x_samples, sizeof(cpFloat));
+	for(unsigned long i=0; i<x_samples; i++) buffer[i] = sample(cpv(cpflerp(bb.l, bb.r, i*x_denom), bb.b), sample_data);
+	
+	for(unsigned long j=0; j<y_samples-1; j++){
+		cpFloat y0 = cpflerp(bb.b, bb.t, (j+0)*y_denom);
+		cpFloat y1 = cpflerp(bb.b, bb.t, (j+1)*y_denom);
+		
+		cpFloat a, b = buffer[0];
+		cpFloat c, d = sample(cpv(bb.l, y1), sample_data);
+		buffer[0] = d;
+		
+		for(unsigned long i=0; i<x_samples-1; i++){
+			cpFloat x0 = cpflerp(bb.l, bb.r, (i+0)*x_denom);
+			cpFloat x1 = cpflerp(bb.l, bb.r, (i+1)*x_denom);
+			
+			a = b, b = buffer[i + 1];
+			c = d, d = sample(cpv(x1, y1), sample_data);
+			buffer[i + 1] = d;
+			
+			cell(t, a, b, c, d, x0, x1, y0, y1, segment, segment_data);
+		}
+	}
+	
+	cpfree(buffer);
+}
+
+
+// TODO should flip this around eventually.
+static inline void
+seg(cpVect v0, cpVect v1, cpMarchSegmentFunc f, void *data)
+{
+	if(!cpveql(v0, v1)) f(v1, v0, data);
+}
+
+// Lerps between two positions based on their sample values.
+static inline cpFloat
+midlerp(cpFloat x0, cpFloat x1, cpFloat s0, cpFloat s1, cpFloat t)
+{
+	return cpflerp(x0, x1, (t - s0)/(s1 - s0));
+}
+
+static void
+cpMarchCellSoft(
+	cpFloat t, cpFloat a, cpFloat b, cpFloat c, cpFloat d,
+	cpFloat x0, cpFloat x1, cpFloat y0, cpFloat y1,
+	cpMarchSegmentFunc segment, void *segment_data
+){
+	// TODO this switch part is super expensive, can it be NEONized?
+	switch((a>t)<<0 | (b>t)<<1 | (c>t)<<2 | (d>t)<<3){
+		case 0x1: seg(cpv(x0, midlerp(y0,y1,a,c,t)), cpv(midlerp(x0,x1,a,b,t), y0), segment, segment_data); break;
+		case 0x2: seg(cpv(midlerp(x0,x1,a,b,t), y0), cpv(x1, midlerp(y0,y1,b,d,t)), segment, segment_data); break;
+		case 0x3: seg(cpv(x0, midlerp(y0,y1,a,c,t)), cpv(x1, midlerp(y0,y1,b,d,t)), segment, segment_data); break;
+		case 0x4: seg(cpv(midlerp(x0,x1,c,d,t), y1), cpv(x0, midlerp(y0,y1,a,c,t)), segment, segment_data); break;
+		case 0x5: seg(cpv(midlerp(x0,x1,c,d,t), y1), cpv(midlerp(x0,x1,a,b,t), y0), segment, segment_data); break;
+		case 0x6: seg(cpv(midlerp(x0,x1,a,b,t), y0), cpv(x1, midlerp(y0,y1,b,d,t)), segment, segment_data);
+							seg(cpv(midlerp(x0,x1,c,d,t), y1), cpv(x0, midlerp(y0,y1,a,c,t)), segment, segment_data); break;
+		case 0x7: seg(cpv(midlerp(x0,x1,c,d,t), y1), cpv(x1, midlerp(y0,y1,b,d,t)), segment, segment_data); break;
+		case 0x8: seg(cpv(x1, midlerp(y0,y1,b,d,t)), cpv(midlerp(x0,x1,c,d,t), y1), segment, segment_data); break;
+		case 0x9: seg(cpv(x0, midlerp(y0,y1,a,c,t)), cpv(midlerp(x0,x1,a,b,t), y0), segment, segment_data);
+							seg(cpv(x1, midlerp(y0,y1,b,d,t)), cpv(midlerp(x0,x1,c,d,t), y1), segment, segment_data); break;
+		case 0xA: seg(cpv(midlerp(x0,x1,a,b,t), y0), cpv(midlerp(x0,x1,c,d,t), y1), segment, segment_data); break;
+		case 0xB: seg(cpv(x0, midlerp(y0,y1,a,c,t)), cpv(midlerp(x0,x1,c,d,t), y1), segment, segment_data); break;
+		case 0xC: seg(cpv(x1, midlerp(y0,y1,b,d,t)), cpv(x0, midlerp(y0,y1,a,c,t)), segment, segment_data); break;
+		case 0xD: seg(cpv(x1, midlerp(y0,y1,b,d,t)), cpv(midlerp(x0,x1,a,b,t), y0), segment, segment_data); break;
+		case 0xE: seg(cpv(midlerp(x0,x1,a,b,t), y0), cpv(x0, midlerp(y0,y1,a,c,t)), segment, segment_data); break;
+		default: break; // 0x0 and 0xF
+	}
+}
+
+void
+cpMarchSoft(
+  cpBB bb, unsigned long x_samples, unsigned long y_samples, cpFloat t,
+  cpMarchSegmentFunc segment, void *segment_data,
+  cpMarchSampleFunc sample, void *sample_data
+){
+	cpMarchCells(bb, x_samples, y_samples, t, segment, segment_data, sample, sample_data, cpMarchCellSoft);
+}
+
+
+// TODO should flip this around eventually.
+static inline void
+segs(cpVect a, cpVect b, cpVect c, cpMarchSegmentFunc f, void *data)
+{
+	seg(b, c, f, data);
+	seg(a, b, f, data);
+}
+
+static void
+cpMarchCellHard(
+	cpFloat t, cpFloat a, cpFloat b, cpFloat c, cpFloat d,
+	cpFloat x0, cpFloat x1, cpFloat y0, cpFloat y1,
+	cpMarchSegmentFunc segment, void *segment_data
+){
+	// midpoints
+	cpFloat xm = cpflerp(x0, x1, 0.5f);
+	cpFloat ym = cpflerp(y0, y1, 0.5f);
+	
+	switch((a>t)<<0 | (b>t)<<1 | (c>t)<<2 | (d>t)<<3){
+		case 0x1: segs(cpv(x0, ym), cpv(xm, ym), cpv(xm, y0), segment, segment_data); break;
+		case 0x2: segs(cpv(xm, y0), cpv(xm, ym), cpv(x1, ym), segment, segment_data); break;
+		case 0x3: seg(cpv(x0, ym), cpv(x1, ym), segment, segment_data); break;
+		case 0x4: segs(cpv(xm, y1), cpv(xm, ym), cpv(x0, ym), segment, segment_data); break;
+		case 0x5: seg(cpv(xm, y1), cpv(xm, y0), segment, segment_data); break;
+		case 0x6: segs(cpv(xm, y0), cpv(xm, ym), cpv(x0, ym), segment, segment_data);
+		          segs(cpv(xm, y1), cpv(xm, ym), cpv(x1, ym), segment, segment_data); break;
+		case 0x7: segs(cpv(xm, y1), cpv(xm, ym), cpv(x1, ym), segment, segment_data); break;
+		case 0x8: segs(cpv(x1, ym), cpv(xm, ym), cpv(xm, y1), segment, segment_data); break;
+		case 0x9: segs(cpv(x1, ym), cpv(xm, ym), cpv(xm, y0), segment, segment_data);
+		          segs(cpv(x0, ym), cpv(xm, ym), cpv(xm, y1), segment, segment_data); break;
+		case 0xA: seg(cpv(xm, y0), cpv(xm, y1), segment, segment_data); break;
+		case 0xB: segs(cpv(x0, ym), cpv(xm, ym), cpv(xm, y1), segment, segment_data); break;
+		case 0xC: seg(cpv(x1, ym), cpv(x0, ym), segment, segment_data); break;
+		case 0xD: segs(cpv(x1, ym), cpv(xm, ym), cpv(xm, y0), segment, segment_data); break;
+		case 0xE: segs(cpv(xm, y0), cpv(xm, ym), cpv(x0, ym), segment, segment_data); break;
+		default: break; // 0x0 and 0xF
+	}
+}
+
+void
+cpMarchHard(
+  cpBB bb, unsigned long x_samples, unsigned long y_samples, cpFloat t,
+  cpMarchSegmentFunc segment, void *segment_data,
+  cpMarchSampleFunc sample, void *sample_data
+){
+	cpMarchCells(bb, x_samples, y_samples, t, segment, segment_data, sample, sample_data, cpMarchCellHard);
+}
diff --git a/Chipmunk2D-7.0.2/src/cpPinJoint.c b/Chipmunk2D-7.0.2/src/cpPinJoint.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpPinJoint.c
@@ -0,0 +1,172 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpPinJoint *joint, cpFloat dt)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	joint->r1 = cpTransformVect(a->transform, cpvsub(joint->anchorA, a->cog));
+	joint->r2 = cpTransformVect(b->transform, cpvsub(joint->anchorB, b->cog));
+	
+	cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
+	cpFloat dist = cpvlength(delta);
+	joint->n = cpvmult(delta, 1.0f/(dist ? dist : (cpFloat)INFINITY));
+	
+	// calculate mass normal
+	joint->nMass = 1.0f/k_scalar(a, b, joint->r1, joint->r2, joint->n);
+	
+	// calculate bias velocity
+	cpFloat maxBias = joint->constraint.maxBias;
+	joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*(dist - joint->dist)/dt, -maxBias, maxBias);
+}
+
+static void
+applyCachedImpulse(cpPinJoint *joint, cpFloat dt_coef)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	cpVect j = cpvmult(joint->n, joint->jnAcc*dt_coef);
+	apply_impulses(a, b, joint->r1, joint->r2, j);
+}
+
+static void
+applyImpulse(cpPinJoint *joint, cpFloat dt)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	cpVect n = joint->n;
+
+	// compute relative velocity
+	cpFloat vrn = normal_relative_velocity(a, b, joint->r1, joint->r2, n);
+	
+	cpFloat jnMax = joint->constraint.maxForce*dt;
+	
+	// compute normal impulse
+	cpFloat jn = (joint->bias - vrn)*joint->nMass;
+	cpFloat jnOld = joint->jnAcc;
+	joint->jnAcc = cpfclamp(jnOld + jn, -jnMax, jnMax);
+	jn = joint->jnAcc - jnOld;
+	
+	// apply impulse
+	apply_impulses(a, b, joint->r1, joint->r2, cpvmult(n, jn));
+}
+
+static cpFloat
+getImpulse(cpPinJoint *joint)
+{
+	return cpfabs(joint->jnAcc);
+}
+
+static const cpConstraintClass klass = {
+	(cpConstraintPreStepImpl)preStep,
+	(cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+	(cpConstraintApplyImpulseImpl)applyImpulse,
+	(cpConstraintGetImpulseImpl)getImpulse,
+};
+
+
+cpPinJoint *
+cpPinJointAlloc(void)
+{
+	return (cpPinJoint *)cpcalloc(1, sizeof(cpPinJoint));
+}
+
+cpPinJoint *
+cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB)
+{
+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+	
+	joint->anchorA = anchorA;
+	joint->anchorB = anchorB;
+	
+	// STATIC_BODY_CHECK
+	cpVect p1 = (a ? cpTransformPoint(a->transform, anchorA) : anchorA);
+	cpVect p2 = (b ? cpTransformPoint(b->transform, anchorB) : anchorB);
+	joint->dist = cpvlength(cpvsub(p2, p1));
+	
+	cpAssertWarn(joint->dist > 0.0, "You created a 0 length pin joint. A pivot joint will be much more stable.");
+
+	joint->jnAcc = 0.0f;
+	
+	return joint;
+}
+
+cpConstraint *
+cpPinJointNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB)
+{
+	return (cpConstraint *)cpPinJointInit(cpPinJointAlloc(), a, b, anchorA, anchorB);
+}
+
+cpBool
+cpConstraintIsPinJoint(const cpConstraint *constraint)
+{
+	return (constraint->klass == &klass);
+}
+
+cpVect
+cpPinJointGetAnchorA(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint.");
+	return ((cpPinJoint *)constraint)->anchorA;
+}
+
+void
+cpPinJointSetAnchorA(cpConstraint *constraint, cpVect anchorA)
+{
+	cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpPinJoint *)constraint)->anchorA = anchorA;
+}
+
+cpVect
+cpPinJointGetAnchorB(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint.");
+	return ((cpPinJoint *)constraint)->anchorB;
+}
+
+void
+cpPinJointSetAnchorB(cpConstraint *constraint, cpVect anchorB)
+{
+	cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpPinJoint *)constraint)->anchorB = anchorB;
+}
+
+cpFloat
+cpPinJointGetDist(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint.");
+	return ((cpPinJoint *)constraint)->dist;
+}
+
+void
+cpPinJointSetDist(cpConstraint *constraint, cpFloat dist)
+{
+	cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpPinJoint *)constraint)->dist = dist;
+}
diff --git a/Chipmunk2D-7.0.2/src/cpPivotJoint.c b/Chipmunk2D-7.0.2/src/cpPivotJoint.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpPivotJoint.c
@@ -0,0 +1,152 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpPivotJoint *joint, cpFloat dt)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	joint->r1 = cpTransformVect(a->transform, cpvsub(joint->anchorA, a->cog));
+	joint->r2 = cpTransformVect(b->transform, cpvsub(joint->anchorB, b->cog));
+	
+	// Calculate mass tensor
+	joint-> k = k_tensor(a, b, joint->r1, joint->r2);
+	
+	// calculate bias velocity
+	cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
+	joint->bias = cpvclamp(cpvmult(delta, -bias_coef(joint->constraint.errorBias, dt)/dt), joint->constraint.maxBias);
+}
+
+static void
+applyCachedImpulse(cpPivotJoint *joint, cpFloat dt_coef)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	apply_impulses(a, b, joint->r1, joint->r2, cpvmult(joint->jAcc, dt_coef));
+}
+
+static void
+applyImpulse(cpPivotJoint *joint, cpFloat dt)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	cpVect r1 = joint->r1;
+	cpVect r2 = joint->r2;
+		
+	// compute relative velocity
+	cpVect vr = relative_velocity(a, b, r1, r2);
+	
+	// compute normal impulse
+	cpVect j = cpMat2x2Transform(joint->k, cpvsub(joint->bias, vr));
+	cpVect jOld = joint->jAcc;
+	joint->jAcc = cpvclamp(cpvadd(joint->jAcc, j), joint->constraint.maxForce*dt);
+	j = cpvsub(joint->jAcc, jOld);
+	
+	// apply impulse
+	apply_impulses(a, b, joint->r1, joint->r2, j);
+}
+
+static cpFloat
+getImpulse(cpConstraint *joint)
+{
+	return cpvlength(((cpPivotJoint *)joint)->jAcc);
+}
+
+static const cpConstraintClass klass = {
+	(cpConstraintPreStepImpl)preStep,
+	(cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+	(cpConstraintApplyImpulseImpl)applyImpulse,
+	(cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpPivotJoint *
+cpPivotJointAlloc(void)
+{
+	return (cpPivotJoint *)cpcalloc(1, sizeof(cpPivotJoint));
+}
+
+cpPivotJoint *
+cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB)
+{
+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+	
+	joint->anchorA = anchorA;
+	joint->anchorB = anchorB;
+	
+	joint->jAcc = cpvzero;
+	
+	return joint;
+}
+
+cpConstraint *
+cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB)
+{
+	return (cpConstraint *)cpPivotJointInit(cpPivotJointAlloc(), a, b, anchorA, anchorB);
+}
+
+cpConstraint *
+cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot)
+{
+	cpVect anchorA = (a ? cpBodyWorldToLocal(a, pivot) : pivot);
+	cpVect anchorB = (b ? cpBodyWorldToLocal(b, pivot) : pivot);
+	return cpPivotJointNew2(a, b, anchorA, anchorB);
+}
+
+cpBool
+cpConstraintIsPivotJoint(const cpConstraint *constraint)
+{
+	return (constraint->klass == &klass);
+}
+
+cpVect
+cpPivotJointGetAnchorA(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsPivotJoint(constraint), "Constraint is not a pivot joint.");
+	return ((cpPivotJoint *)constraint)->anchorA;
+}
+
+void
+cpPivotJointSetAnchorA(cpConstraint *constraint, cpVect anchorA)
+{
+	cpAssertHard(cpConstraintIsPivotJoint(constraint), "Constraint is not a pivot joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpPivotJoint *)constraint)->anchorA = anchorA;
+}
+
+cpVect
+cpPivotJointGetAnchorB(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsPivotJoint(constraint), "Constraint is not a pivot joint.");
+	return ((cpPivotJoint *)constraint)->anchorB;
+}
+
+void
+cpPivotJointSetAnchorB(cpConstraint *constraint, cpVect anchorB)
+{
+	cpAssertHard(cpConstraintIsPivotJoint(constraint), "Constraint is not a pivot joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpPivotJoint *)constraint)->anchorB = anchorB;
+}
diff --git a/Chipmunk2D-7.0.2/src/cpPolyShape.c b/Chipmunk2D-7.0.2/src/cpPolyShape.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpPolyShape.c
@@ -0,0 +1,323 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+#include "chipmunk/chipmunk_unsafe.h"
+
+cpPolyShape *
+cpPolyShapeAlloc(void)
+{
+	return (cpPolyShape *)cpcalloc(1, sizeof(cpPolyShape));
+}
+
+static void
+cpPolyShapeDestroy(cpPolyShape *poly)
+{
+	if(poly->count > CP_POLY_SHAPE_INLINE_ALLOC){
+		cpfree(poly->planes);
+	}
+}
+
+static cpBB
+cpPolyShapeCacheData(cpPolyShape *poly, cpTransform transform)
+{
+	int count = poly->count;
+	struct cpSplittingPlane *dst = poly->planes;
+	struct cpSplittingPlane *src = dst + count;
+	
+	cpFloat l = (cpFloat)INFINITY, r = -(cpFloat)INFINITY;
+	cpFloat b = (cpFloat)INFINITY, t = -(cpFloat)INFINITY;
+	
+	for(int i=0; i<count; i++){
+		cpVect v = cpTransformPoint(transform, src[i].v0);
+		cpVect n = cpTransformVect(transform, src[i].n);
+		
+		dst[i].v0 = v;
+		dst[i].n = n;
+		
+		l = cpfmin(l, v.x);
+		r = cpfmax(r, v.x);
+		b = cpfmin(b, v.y);
+		t = cpfmax(t, v.y);
+	}
+	
+	cpFloat radius = poly->r;
+	return (poly->shape.bb = cpBBNew(l - radius, b - radius, r + radius, t + radius));
+}
+
+static void
+cpPolyShapePointQuery(cpPolyShape *poly, cpVect p, cpPointQueryInfo *info){
+	int count = poly->count;
+	struct cpSplittingPlane *planes = poly->planes;
+	cpFloat r = poly->r;
+	
+	cpVect v0 = planes[count - 1].v0;
+	cpFloat minDist = INFINITY;
+	cpVect closestPoint = cpvzero;
+	cpVect closestNormal = cpvzero;
+	cpBool outside = cpFalse;
+	
+	for(int i=0; i<count; i++){
+		cpVect v1 = planes[i].v0;
+		outside = outside || (cpvdot(planes[i].n, cpvsub(p,v1)) > 0.0f);
+		
+		cpVect closest = cpClosetPointOnSegment(p, v0, v1);
+		
+		cpFloat dist = cpvdist(p, closest);
+		if(dist < minDist){
+			minDist = dist;
+			closestPoint = closest;
+			closestNormal = planes[i].n;
+		}
+		
+		v0 = v1;
+	}
+	
+	cpFloat dist = (outside ? minDist : -minDist);
+	cpVect g = cpvmult(cpvsub(p, closestPoint), 1.0f/dist);
+	
+	info->shape = (cpShape *)poly;
+	info->point = cpvadd(closestPoint, cpvmult(g, r));
+	info->distance = dist - r;
+	
+	// Use the normal of the closest segment if the distance is small.
+	info->gradient = (minDist > MAGIC_EPSILON ? g : closestNormal);
+}
+
+static void
+cpPolyShapeSegmentQuery(cpPolyShape *poly, cpVect a, cpVect b, cpFloat r2, cpSegmentQueryInfo *info)
+{
+	struct cpSplittingPlane *planes = poly->planes;
+	int count = poly->count;
+	cpFloat r = poly->r;
+	cpFloat rsum = r + r2;
+	
+	for(int i=0; i<count; i++){
+		cpVect n = planes[i].n;
+		cpFloat an = cpvdot(a, n);
+		cpFloat d =  an - cpvdot(planes[i].v0, n) - rsum;
+		if(d < 0.0f) continue;
+		
+		cpFloat bn = cpvdot(b, n);
+		cpFloat t = d/(an - bn);
+		if(t < 0.0f || 1.0f < t) continue;
+		
+		cpVect point = cpvlerp(a, b, t);
+		cpFloat dt = cpvcross(n, point);
+		cpFloat dtMin = cpvcross(n, planes[(i - 1 + count)%count].v0);
+		cpFloat dtMax = cpvcross(n, planes[i].v0);
+		
+		if(dtMin <= dt && dt <= dtMax){
+			info->shape = (cpShape *)poly;
+			info->point = cpvsub(cpvlerp(a, b, t), cpvmult(n, r2));
+			info->normal = n;
+			info->alpha = t;
+		}
+	}
+	
+	// Also check against the beveled vertexes.
+	if(rsum > 0.0f){
+		for(int i=0; i<count; i++){
+			cpSegmentQueryInfo circle_info = {NULL, b, cpvzero, 1.0f};
+			CircleSegmentQuery(&poly->shape, planes[i].v0, r, a, b, r2, &circle_info);
+			if(circle_info.alpha < info->alpha) (*info) = circle_info;
+		}
+	}
+}
+
+static void
+SetVerts(cpPolyShape *poly, int count, const cpVect *verts)
+{
+	poly->count = count;
+	if(count <= CP_POLY_SHAPE_INLINE_ALLOC){
+		poly->planes = poly->_planes;
+	} else {
+		poly->planes = (struct cpSplittingPlane *)cpcalloc(2*count, sizeof(struct cpSplittingPlane));
+	}
+	
+	for(int i=0; i<count; i++){
+		cpVect a = verts[(i - 1 + count)%count];
+		cpVect b = verts[i];
+		cpVect n = cpvnormalize(cpvrperp(cpvsub(b, a)));
+		
+		poly->planes[i + count].v0 = b;
+		poly->planes[i + count].n = n;
+	}
+}
+
+static struct cpShapeMassInfo
+cpPolyShapeMassInfo(cpFloat mass, int count, const cpVect *verts, cpFloat radius)
+{
+	// TODO moment is approximate due to radius.
+	
+	cpVect centroid = cpCentroidForPoly(count, verts);
+	struct cpShapeMassInfo info = {
+		mass, cpMomentForPoly(1.0f, count, verts, cpvneg(centroid), radius),
+		centroid,
+		cpAreaForPoly(count, verts, radius),
+	};
+	
+	return info;
+}
+
+static const cpShapeClass polyClass = {
+	CP_POLY_SHAPE,
+	(cpShapeCacheDataImpl)cpPolyShapeCacheData,
+	(cpShapeDestroyImpl)cpPolyShapeDestroy,
+	(cpShapePointQueryImpl)cpPolyShapePointQuery,
+	(cpShapeSegmentQueryImpl)cpPolyShapeSegmentQuery,
+};
+
+cpPolyShape *
+cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int count, const cpVect *verts, cpTransform transform, cpFloat radius)
+{
+	cpVect *hullVerts = (cpVect *)alloca(count*sizeof(cpVect));
+	
+	// Transform the verts before building the hull in case of a negative scale.
+	for(int i=0; i<count; i++) hullVerts[i] = cpTransformPoint(transform, verts[i]);
+	
+	unsigned int hullCount = cpConvexHull(count, hullVerts, hullVerts, NULL, 0.0);
+	return cpPolyShapeInitRaw(poly, body, hullCount, hullVerts, radius);
+}
+
+cpPolyShape *
+cpPolyShapeInitRaw(cpPolyShape *poly, cpBody *body, int count, const cpVect *verts, cpFloat radius)
+{
+	cpShapeInit((cpShape *)poly, &polyClass, body, cpPolyShapeMassInfo(0.0f, count, verts, radius));
+	
+	SetVerts(poly, count, verts);
+	poly->r = radius;
+
+	return poly;
+}
+
+cpShape *
+cpPolyShapeNew(cpBody *body, int count, const cpVect *verts, cpTransform transform, cpFloat radius)
+{
+	return (cpShape *)cpPolyShapeInit(cpPolyShapeAlloc(), body, count, verts, transform, radius);
+}
+
+cpShape *
+cpPolyShapeNewRaw(cpBody *body, int count, const cpVect *verts, cpFloat radius)
+{
+	return (cpShape *)cpPolyShapeInitRaw(cpPolyShapeAlloc(), body, count, verts, radius);
+}
+
+cpPolyShape *
+cpBoxShapeInit(cpPolyShape *poly, cpBody *body, cpFloat width, cpFloat height, cpFloat radius)
+{
+	cpFloat hw = width/2.0f;
+	cpFloat hh = height/2.0f;
+	
+	return cpBoxShapeInit2(poly, body, cpBBNew(-hw, -hh, hw, hh), radius);
+}
+
+cpPolyShape *
+cpBoxShapeInit2(cpPolyShape *poly, cpBody *body, cpBB box, cpFloat radius)
+{
+	cpVect verts[] = {
+		cpv(box.r, box.b),
+		cpv(box.r, box.t),
+		cpv(box.l, box.t),
+		cpv(box.l, box.b),
+	};
+	
+	return cpPolyShapeInitRaw(poly, body, 4, verts, radius);
+}
+
+cpShape *
+cpBoxShapeNew(cpBody *body, cpFloat width, cpFloat height, cpFloat radius)
+{
+	return (cpShape *)cpBoxShapeInit(cpPolyShapeAlloc(), body, width, height, radius);
+}
+
+cpShape *
+cpBoxShapeNew2(cpBody *body, cpBB box, cpFloat radius)
+{
+	return (cpShape *)cpBoxShapeInit2(cpPolyShapeAlloc(), body, box, radius);
+}
+
+int
+cpPolyShapeGetCount(const cpShape *shape)
+{
+	cpAssertHard(shape->klass == &polyClass, "Shape is not a poly shape.");
+	return ((cpPolyShape *)shape)->count;
+}
+
+cpVect
+cpPolyShapeGetVert(const cpShape *shape, int i)
+{
+	cpAssertHard(shape->klass == &polyClass, "Shape is not a poly shape.");
+	
+	int count = cpPolyShapeGetCount(shape);
+	cpAssertHard(0 <= i && i < count, "Index out of range.");
+	
+	return ((cpPolyShape *)shape)->planes[i + count].v0;
+}
+
+cpFloat
+cpPolyShapeGetRadius(const cpShape *shape)
+{
+	cpAssertHard(shape->klass == &polyClass, "Shape is not a poly shape.");
+	return ((cpPolyShape *)shape)->r;
+}
+
+// Unsafe API (chipmunk_unsafe.h)
+
+void
+cpPolyShapeSetVerts(cpShape *shape, int count, cpVect *verts, cpTransform transform)
+{
+	cpVect *hullVerts = (cpVect *)alloca(count*sizeof(cpVect));
+	
+	// Transform the verts before building the hull in case of a negative scale.
+	for(int i=0; i<count; i++) hullVerts[i] = cpTransformPoint(transform, verts[i]);
+	
+	unsigned int hullCount = cpConvexHull(count, hullVerts, hullVerts, NULL, 0.0);
+	cpPolyShapeSetVertsRaw(shape, hullCount, hullVerts);
+}
+
+void
+cpPolyShapeSetVertsRaw(cpShape *shape, int count, cpVect *verts)
+{
+	cpAssertHard(shape->klass == &polyClass, "Shape is not a poly shape.");
+	cpPolyShape *poly = (cpPolyShape *)shape;
+	cpPolyShapeDestroy(poly);
+	
+	SetVerts(poly, count, verts);
+	
+	cpFloat mass = shape->massInfo.m;
+	shape->massInfo = cpPolyShapeMassInfo(shape->massInfo.m, count, verts, poly->r);
+	if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body);
+}
+
+void
+cpPolyShapeSetRadius(cpShape *shape, cpFloat radius)
+{
+	cpAssertHard(shape->klass == &polyClass, "Shape is not a poly shape.");
+	cpPolyShape *poly = (cpPolyShape *)shape;
+	poly->r = radius;
+	
+	
+	// TODO radius is not handled by moment/area
+//	cpFloat mass = shape->massInfo.m;
+//	shape->massInfo = cpPolyShapeMassInfo(shape->massInfo.m, poly->count, poly->verts, poly->r);
+//	if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body);
+}
diff --git a/Chipmunk2D-7.0.2/src/cpPolyline.c b/Chipmunk2D-7.0.2/src/cpPolyline.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpPolyline.c
@@ -0,0 +1,652 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "chipmunk/chipmunk_private.h"
+#include "chipmunk/cpPolyline.h"
+
+
+static inline int Next(int i, int count){return (i+1)%count;}
+
+//MARK: Polylines
+
+#define DEFAULT_POLYLINE_CAPACITY 16
+
+static int
+cpPolylineSizeForCapacity(int capacity)
+{
+	return sizeof(cpPolyline) + capacity*sizeof(cpVect);
+}
+
+static cpPolyline *
+cpPolylineMake(int capacity)
+{
+	capacity = (capacity > DEFAULT_POLYLINE_CAPACITY ? capacity : DEFAULT_POLYLINE_CAPACITY);
+	
+	cpPolyline *line = (cpPolyline *)cpcalloc(1, cpPolylineSizeForCapacity(capacity));
+	line->count = 0;
+	line->capacity = capacity;
+	
+	return line;
+}
+
+static cpPolyline *
+cpPolylineMake2(int capacity, cpVect a, cpVect b)
+{
+	cpPolyline *line = cpPolylineMake(capacity);
+	line->count = 2;
+	line->verts[0] = a;
+	line->verts[1] = b;
+	
+	return line;
+}
+
+static cpPolyline *
+cpPolylineShrink(cpPolyline *line)
+{
+	line->capacity = line->count;
+	return (cpPolyline*) cprealloc(line, cpPolylineSizeForCapacity(line->count));
+}
+
+void
+cpPolylineFree(cpPolyline *line)
+{
+	cpfree(line);
+}
+
+// Grow the allocated memory for a polyline.
+static cpPolyline *
+cpPolylineGrow(cpPolyline *line, int count)
+{
+  line->count += count;
+  
+  int capacity = line->capacity;
+  while(line->count > capacity) capacity *= 2;
+  
+  if(line->capacity < capacity){
+    line->capacity = capacity;
+		line = (cpPolyline*) cprealloc(line, cpPolylineSizeForCapacity(capacity));
+  }
+	
+	return line;
+}
+
+// Push v onto the end of line.
+static cpPolyline *
+cpPolylinePush(cpPolyline *line, cpVect v)
+{
+  int count = line->count;
+  line = cpPolylineGrow(line, 1);
+  line->verts[count] = v;
+	
+	return line;
+}
+
+// Push v onto the beginning of line.
+static cpPolyline *
+cpPolylineEnqueue(cpPolyline *line, cpVect v)
+{
+	// TODO could optimize this to grow in both directions.
+	// Probably doesn't matter though.
+  int count = line->count;
+  line = cpPolylineGrow(line, 1);
+  memmove(line->verts + 1, line->verts, count*sizeof(cpVect));
+  line->verts[0] = v;
+	
+	return line;
+}
+
+// Returns true if the polyline starts and ends with the same vertex.
+cpBool
+cpPolylineIsClosed(cpPolyline *line)
+{
+	return (line->count > 1 && cpveql(line->verts[0], line->verts[line->count-1]));
+}
+
+// Check if a cpPolyline is longer than a certain length
+// Takes a range which can wrap around if the polyline is looped.
+static cpBool
+cpPolylineIsShort(cpVect *points, int count, int start, int end, cpFloat min)
+{
+  cpFloat length = 0.0f;
+	for(int i=start; i!=end; i=Next(i, count)){
+		length += cpvdist(points[i], points[Next(i, count)]);
+		if(length > min) return cpFalse;
+	}
+  
+  return cpTrue;
+}
+
+//MARK: Polyline Simplification
+
+static inline cpFloat
+Sharpness(cpVect a, cpVect b, cpVect c)
+{
+	// TODO could speed this up by caching the normals instead of calculating each twice.
+  return cpvdot(cpvnormalize(cpvsub(a, b)), cpvnormalize(cpvsub(c, b)));
+}
+
+// Join similar adjacent line segments together. Works well for hard edged shapes.
+// 'tol' is the minimum anglular difference in radians of a vertex.
+cpPolyline *
+cpPolylineSimplifyVertexes(cpPolyline *line, cpFloat tol)
+{
+	cpPolyline *reduced = cpPolylineMake2(0, line->verts[0], line->verts[1]);
+	
+	cpFloat minSharp = -cpfcos(tol);
+	
+	for(int i=2; i<line->count; i++){
+		cpVect vert = line->verts[i];
+		cpFloat sharp = Sharpness(reduced->verts[reduced->count - 2], reduced->verts[reduced->count - 1], vert);
+		
+		if(sharp <= minSharp){
+			reduced->verts[reduced->count - 1] = vert;
+		} else {
+			reduced = cpPolylinePush(reduced, vert);
+		}
+	}
+	
+	if(
+		cpPolylineIsClosed(line) &&
+		Sharpness(reduced->verts[reduced->count - 2], reduced->verts[0], reduced->verts[1]) < minSharp
+	){
+		reduced->verts[0] = reduced->verts[reduced->count - 2];
+		reduced->count--;
+	}
+	
+	// TODO shrink
+	return reduced;
+}
+
+// Recursive function used by cpPolylineSimplifyCurves().
+static cpPolyline *
+DouglasPeucker(
+	cpVect *verts, cpPolyline *reduced,
+	int length, int start, int end,
+	cpFloat min, cpFloat tol
+){
+	// Early exit if the points are adjacent
+  if((end - start + length)%length < 2) return reduced;
+  
+	cpVect a = verts[start];
+	cpVect b = verts[end];
+	
+	// Check if the length is below the threshold
+	if(cpvnear(a, b, min) && cpPolylineIsShort(verts, length, start, end, min)) return reduced;
+	
+	// Find the maximal vertex to split and recurse on
+	cpFloat max = 0.0;
+	int maxi = start;
+	
+	cpVect n = cpvnormalize(cpvperp(cpvsub(b, a)));
+	cpFloat d = cpvdot(n, a);
+	
+	for(int i=Next(start, length); i!=end; i=Next(i, length)){
+		cpFloat dist = fabs(cpvdot(n, verts[i]) - d);
+		
+		if(dist > max){
+			max = dist;
+			maxi = i;
+		}
+	}
+	
+	if(max > tol){
+    reduced = DouglasPeucker(verts, reduced, length, start, maxi, min, tol);
+		reduced = cpPolylinePush(reduced, verts[maxi]);
+    reduced = DouglasPeucker(verts, reduced, length, maxi, end, min, tol);
+	}
+	
+	return reduced;
+}
+
+// Recursively reduce the vertex count on a polyline. Works best for smooth shapes.
+// 'tol' is the maximum error for the reduction.
+// The reduced polyline will never be farther than this distance from the original polyline.
+cpPolyline *
+cpPolylineSimplifyCurves(cpPolyline *line, cpFloat tol)
+{
+	cpPolyline *reduced = cpPolylineMake(line->count);
+	
+	cpFloat min = tol/2.0f;
+  
+  if(cpPolylineIsClosed(line)){
+		int start, end;
+    cpLoopIndexes(line->verts, line->count - 1, &start, &end);
+    
+		reduced = cpPolylinePush(reduced, line->verts[start]);
+		reduced = DouglasPeucker(line->verts, reduced, line->count - 1, start, end, min, tol);
+		reduced = cpPolylinePush(reduced, line->verts[end]);
+		reduced = DouglasPeucker(line->verts, reduced, line->count - 1, end, start, min, tol);
+		reduced = cpPolylinePush(reduced, line->verts[start]);
+  } else {
+		reduced = cpPolylinePush(reduced, line->verts[0]);
+		reduced = DouglasPeucker(line->verts, reduced, line->count, 0, line->count - 1, min, tol);
+		reduced = cpPolylinePush(reduced, line->verts[line->count - 1]);
+  }
+	
+	return cpPolylineShrink(reduced);
+}
+
+//MARK: Polyline Sets
+
+cpPolylineSet *
+cpPolylineSetAlloc(void)
+{
+	return (cpPolylineSet *)cpcalloc(1, sizeof(cpPolylineSet));
+}
+
+cpPolylineSet *
+cpPolylineSetInit(cpPolylineSet *set)
+{
+	set->count = 0;
+	set->capacity = 8;
+	set->lines = (cpPolyline**) cpcalloc(set->capacity, sizeof(cpPolyline));
+	
+  return set;
+}
+
+
+cpPolylineSet *
+cpPolylineSetNew(void)
+{
+	return cpPolylineSetInit(cpPolylineSetAlloc());
+}
+
+void
+cpPolylineSetDestroy(cpPolylineSet *set, cpBool freePolylines)
+{
+	if(freePolylines){
+		for(int i=0; i<set->count; i++){
+			cpPolylineFree(set->lines[i]);
+		}
+	}
+	
+	cpfree(set->lines);
+}
+
+
+void
+cpPolylineSetFree(cpPolylineSet *set, cpBool freePolylines)
+{
+	if(set){
+		cpPolylineSetDestroy(set, freePolylines);
+		cpfree(set);
+	}
+}
+
+// Find the polyline that ends with v.
+static int
+cpPolylineSetFindEnds(cpPolylineSet *set, cpVect v){
+	int count = set->count;
+	cpPolyline **lines = set->lines;
+	
+  for(int i=0; i<count; i++){
+		cpPolyline *line = lines[i];
+    if(cpveql(line->verts[line->count - 1], v)) return i;
+  }
+  
+  return -1;
+}
+
+// Find the polyline that starts with v.
+static int
+cpPolylineSetFindStarts(cpPolylineSet *set, cpVect v){
+	int count = set->count;
+	cpPolyline **lines = set->lines;
+	
+  for(int i=0; i<count; i++){
+    if(cpveql(lines[i]->verts[0], v)) return i;
+  }
+  
+  return -1;
+}
+
+// Add a new polyline to a polyline set.
+static void
+cpPolylineSetPush(cpPolylineSet *set, cpPolyline *line)
+{
+  // grow set
+  set->count++;
+  if(set->count > set->capacity){
+    set->capacity *= 2;
+    set->lines = (cpPolyline**) cprealloc(set->lines, set->capacity*sizeof(cpPolyline));
+  }
+  
+	set->lines[set->count - 1] = line;
+}
+
+// Add a new polyline to a polyline set.
+static void
+cpPolylineSetAdd(cpPolylineSet *set, cpVect v0, cpVect v1)
+{
+	cpPolylineSetPush(set, cpPolylineMake2(DEFAULT_POLYLINE_CAPACITY, v0, v1));
+}
+
+// Join two cpPolylines in a polyline set together.
+static void
+cpPolylineSetJoin(cpPolylineSet *set, int before, int after)
+{
+  cpPolyline *lbefore = set->lines[before];
+  cpPolyline *lafter = set->lines[after];
+  
+  // append
+  int count = lbefore->count;
+  lbefore = cpPolylineGrow(lbefore, lafter->count);
+  memmove(lbefore->verts + count, lafter->verts, lafter->count*sizeof(cpVect));
+	set->lines[before] = lbefore;
+  
+  // delete lafter
+  set->count--;
+	cpPolylineFree(set->lines[after]);
+  set->lines[after] = set->lines[set->count];
+}
+
+// Add a segment to a polyline set.
+// A segment will either start a new polyline, join two others, or add to or loop an existing polyline.
+void
+cpPolylineSetCollectSegment(cpVect v0, cpVect v1, cpPolylineSet *lines)
+{
+  int before = cpPolylineSetFindEnds(lines, v0);
+  int after = cpPolylineSetFindStarts(lines, v1);
+  
+  if(before >= 0 && after >= 0){
+    if(before == after){
+      // loop by pushing v1 onto before
+      lines->lines[before] = cpPolylinePush(lines->lines[before], v1);
+    } else {
+      // join before and after
+      cpPolylineSetJoin(lines, before, after);
+    }
+  } else if(before >= 0){
+    // push v1 onto before
+    lines->lines[before] = cpPolylinePush(lines->lines[before], v1);
+  } else if(after >= 0){
+    // enqueue v0 onto after
+    lines->lines[after] = cpPolylineEnqueue(lines->lines[after], v0);
+  } else {
+    // create new line from v0 and v1
+    cpPolylineSetAdd(lines, v0, v1);
+  }
+}
+
+//MARK: Convex Hull Functions
+
+cpPolyline *
+cpPolylineToConvexHull(cpPolyline *line, cpFloat tol)
+{
+	cpPolyline *hull = cpPolylineMake(line->count + 1);
+	hull->count = cpConvexHull(line->count, line->verts, hull->verts, NULL, tol);
+	hull = cpPolylinePush(hull, hull->verts[0]);
+	
+	return cpPolylineShrink(hull);
+}
+
+//MARK: Approximate Concave Decompostition
+
+struct Notch {
+	int i;
+	cpFloat d;
+	cpVect v;
+	cpVect n;
+};
+
+static cpFloat
+FindSteiner(int count, cpVect *verts, struct Notch notch)
+{
+	cpFloat min = INFINITY;
+	cpFloat feature = -1.0;
+	
+	for(int i=1; i<count-1; i++){
+		int index = (notch.i + i)%count;
+		
+		cpVect seg_a = verts[index];
+		cpVect seg_b = verts[Next(index, count)];
+		
+		cpFloat thing_a = cpvcross(notch.n, cpvsub(seg_a, notch.v));
+		cpFloat thing_b = cpvcross(notch.n, cpvsub(seg_b, notch.v));
+		if(thing_a*thing_b <= 0.0){
+			cpFloat t = thing_a/(thing_a - thing_b);
+			cpFloat dist = cpvdot(notch.n, cpvsub(cpvlerp(seg_a, seg_b, t), notch.v));
+			
+			if(dist >= 0.0 && dist <= min){
+				min = dist;
+				feature = index + t;
+			}
+		}
+	}
+	
+	return feature;
+}
+
+//static cpFloat
+//FindSteiner2(cpVect *verts, int count, struct Notch notch)
+//{
+//	cpVect a = verts[(notch.i + count - 1)%count];
+//	cpVect b = verts[(notch.i + 1)%count];
+//	cpVect n = cpvnormalize(cpvadd(cpvnormalize(cpvsub(notch.v, a)), cpvnormalize(cpvsub(notch.v, b))));
+//	
+//	cpFloat min = INFINITY;
+//	cpFloat feature = -1.0;
+//	
+//	for(int i=1; i<count-1; i++){
+//		int index = (notch.i + i)%count;
+//		
+//		cpVect seg_a = verts[index];
+//		cpVect seg_b = verts[Next(index, count)];
+//		
+//		cpFloat thing_a = cpvcross(n, cpvsub(seg_a, notch.v));
+//		cpFloat thing_b = cpvcross(n, cpvsub(seg_b, notch.v));
+//		if(thing_a*thing_b <= 0.0){
+//			cpFloat t = thing_a/(thing_a - thing_b);
+//			cpFloat dist = cpvdot(n, cpvsub(cpvlerp(seg_a, seg_b, t), notch.v));
+//			
+//			if(dist >= 0.0 && dist <= min){
+//				min = dist;
+//				feature = index + t;
+//			}
+//		}
+//	}
+//	
+//	cpAssertSoft(feature >= 0.0, "No closest features detected. This is likely due to a self intersecting polygon.");
+//	return feature;
+//}
+
+//struct Range {cpFloat min, max;};
+//static inline struct Range
+//clip_range(cpVect delta_a, cpVect delta_b, cpVect clip)
+//{
+//	cpFloat da = cpvcross(delta_a, clip);
+//	cpFloat db = cpvcross(delta_b, clip);
+//	cpFloat clamp = da/(da - db);
+//	if(da > db){
+//		return (struct Range){-INFINITY, clamp};
+//	} else if(da < db){
+//		return (struct Range){clamp, INFINITY};
+//	} else {
+//		return (struct Range){-INFINITY, INFINITY};
+//	}
+//}
+//
+//static cpFloat
+//FindSteiner3(cpVect *verts, int count, struct Notch notch)
+//{
+//	cpFloat min = INFINITY;
+//	cpFloat feature = -1.0;
+//	
+//	cpVect support_a = verts[(notch.i - 1 + count)%count];
+//	cpVect support_b = verts[(notch.i + 1)%count];
+//	
+//	cpVect clip_a = cpvlerp(support_a, support_b, 0.1);
+//	cpVect clip_b = cpvlerp(support_b, support_b, 0.9);
+//	
+//	for(int i=1; i<count - 1; i++){
+//		int index = (notch.i + i)%count;
+//		cpVect seg_a = verts[index];
+//		cpVect seg_b = verts[Next(index, count)];
+//		
+//		cpVect delta_a = cpvsub(seg_a, notch.v);
+//		cpVect delta_b = cpvsub(seg_b, notch.v);
+//		
+//		// Ignore if the segment faces away from the point.
+//		if(cpvcross(delta_b, delta_a) > 0.0){
+//			struct Range range1 = clip_range(delta_a, delta_b, cpvsub(notch.v, clip_a));
+//			struct Range range2 = clip_range(delta_a, delta_b, cpvsub(clip_b, notch.v));
+//			
+//			cpFloat min_t = cpfmax(0.0, cpfmax(range1.min, range2.min));
+//			cpFloat max_t = cpfmin(1.0, cpfmin(range1.max, range2.max));
+//			
+//			// Ignore if the segment has been completely clipped away.
+//			if(min_t < max_t){
+//				cpVect seg_delta = cpvsub(seg_b, seg_a);
+//				cpFloat closest_t = cpfclamp(cpvdot(seg_delta, cpvsub(notch.v, seg_a))/cpvlengthsq(seg_delta), min_t, max_t);
+//				cpVect closest = cpvlerp(seg_a, seg_b, closest_t);
+//				
+//				cpFloat dist = cpvdistsq(notch.v, closest);
+//				if(dist < min){
+//					min = dist;
+//					feature = index + closest_t;
+//				}
+//			}
+//		}
+//	}
+//	
+//	cpAssertWarn(feature >= 0.0, "Internal Error: No closest features detected.");
+//	return feature;
+//}
+
+//static cpBool
+//VertexUnobscured(int count, cpVect *verts, int index, int notch_i)
+//{
+//	cpVect v = verts[notch_i];
+//	cpVect n = cpvnormalize(cpvsub(verts[index], v));
+//	
+//	for(int i=0; i<count; i++){
+//		if(i == index || i == Next(i, count) || i == notch_i || i == Next(notch_i, count)) continue;
+//		
+//		cpVect seg_a = verts[i];
+//		cpVect seg_b = verts[Next(i, count)];
+//		
+//		cpFloat thing_a = cpvcross(n, cpvsub(seg_a, v));
+//		cpFloat thing_b = cpvcross(n, cpvsub(seg_b, v));
+//		if(thing_a*thing_b <= 0.0) return cpTrue;
+//	}
+//	
+//	return cpFalse;
+//}
+//
+//static cpFloat
+//FindSteiner4(int count, cpVect *verts, struct Notch notch, cpFloat *convexity)
+//{
+//	cpFloat min = INFINITY;
+//	cpFloat feature = -1.0;
+//	
+//	for(int i=Next(notch.b, count); i!=notch.a; i=Next(i, count)){
+//		cpVect v = verts[i];
+//		cpFloat weight = (1.0 + 0.1*convexity[i])/(1.0*cpvdist(notch.v, v));
+//		
+//		if(weight <= min && VertexUnobscured(count, verts, i, notch.i)){
+//			min = weight;
+//			feature = i;
+//		}
+//	}
+//	
+//	cpAssertSoft(feature >= 0.0, "No closest features detected. This is likely due to a self intersecting polygon.");
+//	return feature;
+//}
+
+static struct Notch
+DeepestNotch(int count, cpVect *verts, int hullCount, cpVect *hullVerts, int first, cpFloat tol)
+{
+	struct Notch notch = {};
+	int j = Next(first, count);
+	
+	for(int i=0; i<hullCount; i++){
+		cpVect a = hullVerts[i];
+		cpVect b = hullVerts[Next(i, hullCount)];
+		
+		// TODO use a cross check instead?
+		cpVect n = cpvnormalize(cpvrperp(cpvsub(a, b)));
+		cpFloat d = cpvdot(n, a);
+		
+		cpVect v = verts[j];
+		while(!cpveql(v, b)){
+			cpFloat depth = cpvdot(n, v) - d;
+			
+			if(depth > notch.d){
+				notch.d = depth;
+				notch.i = j;
+				notch.v = v;
+				notch.n = n;
+			}
+			
+			j = Next(j, count);
+			v = verts[j];
+		}
+		
+		j = Next(j, count);
+	}
+	
+	return notch;
+}
+
+static inline int IMAX(int a, int b){return (a > b ? a : b);}
+
+static void
+ApproximateConcaveDecomposition(cpVect *verts, int count, cpFloat tol, cpPolylineSet *set)
+{
+	int first;
+	cpVect *hullVerts = (cpVect*) alloca(count*sizeof(cpVect));
+	int hullCount = cpConvexHull(count, verts, hullVerts, &first, 0.0);
+	
+	if(hullCount != count){
+		struct Notch notch = DeepestNotch(count, verts, hullCount, hullVerts, first, tol);
+		
+		if(notch.d > tol){
+			cpFloat steiner_it = FindSteiner(count, verts, notch);
+			
+			if(steiner_it >= 0.0){
+				int steiner_i = (int)steiner_it;
+				cpVect steiner = cpvlerp(verts[steiner_i], verts[Next(steiner_i, count)], steiner_it - steiner_i);
+				
+				// Vertex counts NOT including the steiner point.
+				int sub1_count = (steiner_i - notch.i + count)%count + 1;
+				int sub2_count = count - (steiner_i - notch.i + count)%count;
+				cpVect *scratch = (cpVect*) alloca((IMAX(sub1_count, sub2_count) + 1)*sizeof(cpVect));
+				
+				for(int i=0; i<sub1_count; i++) scratch[i] = verts[(notch.i + i)%count];
+				scratch[sub1_count] = steiner;
+				ApproximateConcaveDecomposition(scratch, sub1_count + 1, tol, set);
+				
+				for(int i=0; i<sub2_count; i++) scratch[i] = verts[(steiner_i + 1 + i)%count];
+				scratch[sub2_count] = steiner;
+				ApproximateConcaveDecomposition(scratch, sub2_count + 1, tol, set);
+				
+				return;
+			}
+		}
+	}
+	
+	cpPolyline *hull = cpPolylineMake(hullCount + 1);
+	
+	memcpy(hull->verts, hullVerts, hullCount*sizeof(cpVect));
+	hull->verts[hullCount] = hullVerts[0];
+	hull->count = hullCount + 1;
+	
+	cpPolylineSetPush(set, hull);
+}
+
+cpPolylineSet *
+cpPolylineConvexDecomposition_BETA(cpPolyline *line, cpFloat tol)
+{
+	cpAssertSoft(cpPolylineIsClosed(line), "Cannot decompose an open polygon.");
+	cpAssertSoft(cpAreaForPoly(line->count, line->verts, 0.0) >= 0.0, "Winding is backwards. (Are you passing a hole?)");
+	
+	cpPolylineSet *set = cpPolylineSetNew();
+	ApproximateConcaveDecomposition(line->verts, line->count - 1, tol, set);
+	
+	return set;
+}
diff --git a/Chipmunk2D-7.0.2/src/cpRatchetJoint.c b/Chipmunk2D-7.0.2/src/cpRatchetJoint.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpRatchetJoint.c
@@ -0,0 +1,179 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpRatchetJoint *joint, cpFloat dt)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	cpFloat angle = joint->angle;
+	cpFloat phase = joint->phase;
+	cpFloat ratchet = joint->ratchet;
+	
+	cpFloat delta = b->a - a->a;
+	cpFloat diff = angle - delta;
+	cpFloat pdist = 0.0f;
+	
+	if(diff*ratchet > 0.0f){
+		pdist = diff;
+	} else {
+		joint->angle = cpffloor((delta - phase)/ratchet)*ratchet + phase;
+	}
+	
+	// calculate moment of inertia coefficient.
+	joint->iSum = 1.0f/(a->i_inv + b->i_inv);
+	
+	// calculate bias velocity
+	cpFloat maxBias = joint->constraint.maxBias;
+	joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias);
+
+	// If the bias is 0, the joint is not at a limit. Reset the impulse.
+	if(!joint->bias) joint->jAcc = 0.0f;
+}
+
+static void
+applyCachedImpulse(cpRatchetJoint *joint, cpFloat dt_coef)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	cpFloat j = joint->jAcc*dt_coef;
+	a->w -= j*a->i_inv;
+	b->w += j*b->i_inv;
+}
+
+static void
+applyImpulse(cpRatchetJoint *joint, cpFloat dt)
+{
+	if(!joint->bias) return; // early exit
+
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	// compute relative rotational velocity
+	cpFloat wr = b->w - a->w;
+	cpFloat ratchet = joint->ratchet;
+	
+	cpFloat jMax = joint->constraint.maxForce*dt;
+	
+	// compute normal impulse	
+	cpFloat j = -(joint->bias + wr)*joint->iSum;
+	cpFloat jOld = joint->jAcc;
+	joint->jAcc = cpfclamp((jOld + j)*ratchet, 0.0f, jMax*cpfabs(ratchet))/ratchet;
+	j = joint->jAcc - jOld;
+	
+	// apply impulse
+	a->w -= j*a->i_inv;
+	b->w += j*b->i_inv;
+}
+
+static cpFloat
+getImpulse(cpRatchetJoint *joint)
+{
+	return cpfabs(joint->jAcc);
+}
+
+static const cpConstraintClass klass = {
+	(cpConstraintPreStepImpl)preStep,
+	(cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+	(cpConstraintApplyImpulseImpl)applyImpulse,
+	(cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpRatchetJoint *
+cpRatchetJointAlloc(void)
+{
+	return (cpRatchetJoint *)cpcalloc(1, sizeof(cpRatchetJoint));
+}
+
+cpRatchetJoint *
+cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet)
+{
+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+	
+	joint->angle = 0.0f;
+	joint->phase = phase;
+	joint->ratchet = ratchet;
+	
+	// STATIC_BODY_CHECK
+	joint->angle = (b ? b->a : 0.0f) - (a ? a->a : 0.0f);
+	
+	return joint;
+}
+
+cpConstraint *
+cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet)
+{
+	return (cpConstraint *)cpRatchetJointInit(cpRatchetJointAlloc(), a, b, phase, ratchet);
+}
+
+cpBool
+cpConstraintIsRatchetJoint(const cpConstraint *constraint)
+{
+	return (constraint->klass == &klass);
+}
+
+cpFloat
+cpRatchetJointGetAngle(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint.");
+	return ((cpRatchetJoint *)constraint)->angle;
+}
+
+void
+cpRatchetJointSetAngle(cpConstraint *constraint, cpFloat angle)
+{
+	cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpRatchetJoint *)constraint)->angle = angle;
+}
+
+cpFloat
+cpRatchetJointGetPhase(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint.");
+	return ((cpRatchetJoint *)constraint)->phase;
+}
+
+void
+cpRatchetJointSetPhase(cpConstraint *constraint, cpFloat phase)
+{
+	cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpRatchetJoint *)constraint)->phase = phase;
+}
+cpFloat
+cpRatchetJointGetRatchet(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint.");
+	return ((cpRatchetJoint *)constraint)->ratchet;
+}
+
+void
+cpRatchetJointSetRatchet(cpConstraint *constraint, cpFloat ratchet)
+{
+	cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpRatchetJoint *)constraint)->ratchet = ratchet;
+}
diff --git a/Chipmunk2D-7.0.2/src/cpRobust.c b/Chipmunk2D-7.0.2/src/cpRobust.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpRobust.c
@@ -0,0 +1,13 @@
+#include "chipmunk/cpRobust.h"
+
+
+cpBool
+cpCheckPointGreater(const cpVect a, const cpVect b, const cpVect c)
+{
+	return (b.y - a.y)*(a.x + b.x - 2*c.x) > (b.x - a.x)*(a.y + b.y - 2*c.y);
+}
+
+cpBool
+cpCheckAxis(cpVect v0, cpVect v1, cpVect p, cpVect n){
+	return cpvdot(p, n) <= cpfmax(cpvdot(v0, n), cpvdot(v1, n));
+}
diff --git a/Chipmunk2D-7.0.2/src/cpRotaryLimitJoint.c b/Chipmunk2D-7.0.2/src/cpRotaryLimitJoint.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpRotaryLimitJoint.c
@@ -0,0 +1,160 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpRotaryLimitJoint *joint, cpFloat dt)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	cpFloat dist = b->a - a->a;
+	cpFloat pdist = 0.0f;
+	if(dist > joint->max) {
+		pdist = joint->max - dist;
+	} else if(dist < joint->min) {
+		pdist = joint->min - dist;
+	}
+	
+	// calculate moment of inertia coefficient.
+	joint->iSum = 1.0f/(a->i_inv + b->i_inv);
+	
+	// calculate bias velocity
+	cpFloat maxBias = joint->constraint.maxBias;
+	joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias);
+
+	// If the bias is 0, the joint is not at a limit. Reset the impulse.
+	if(!joint->bias) joint->jAcc = 0.0f;
+}
+
+static void
+applyCachedImpulse(cpRotaryLimitJoint *joint, cpFloat dt_coef)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	cpFloat j = joint->jAcc*dt_coef;
+	a->w -= j*a->i_inv;
+	b->w += j*b->i_inv;
+}
+
+static void
+applyImpulse(cpRotaryLimitJoint *joint, cpFloat dt)
+{
+	if(!joint->bias) return; // early exit
+
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	// compute relative rotational velocity
+	cpFloat wr = b->w - a->w;
+	
+	cpFloat jMax = joint->constraint.maxForce*dt;
+	
+	// compute normal impulse	
+	cpFloat j = -(joint->bias + wr)*joint->iSum;
+	cpFloat jOld = joint->jAcc;
+	if(joint->bias < 0.0f){
+		joint->jAcc = cpfclamp(jOld + j, 0.0f, jMax);
+	} else {
+		joint->jAcc = cpfclamp(jOld + j, -jMax, 0.0f);
+	}
+	j = joint->jAcc - jOld;
+	
+	// apply impulse
+	a->w -= j*a->i_inv;
+	b->w += j*b->i_inv;
+}
+
+static cpFloat
+getImpulse(cpRotaryLimitJoint *joint)
+{
+	return cpfabs(joint->jAcc);
+}
+
+static const cpConstraintClass klass = {
+	(cpConstraintPreStepImpl)preStep,
+	(cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+	(cpConstraintApplyImpulseImpl)applyImpulse,
+	(cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpRotaryLimitJoint *
+cpRotaryLimitJointAlloc(void)
+{
+	return (cpRotaryLimitJoint *)cpcalloc(1, sizeof(cpRotaryLimitJoint));
+}
+
+cpRotaryLimitJoint *
+cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max)
+{
+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+	
+	joint->min = min;
+	joint->max  = max;
+	
+	joint->jAcc = 0.0f;
+	
+	return joint;
+}
+
+cpConstraint *
+cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max)
+{
+	return (cpConstraint *)cpRotaryLimitJointInit(cpRotaryLimitJointAlloc(), a, b, min, max);
+}
+
+cpBool
+cpConstraintIsRotaryLimitJoint(const cpConstraint *constraint)
+{
+	return (constraint->klass == &klass);
+}
+
+cpFloat
+cpRotaryLimitJointGetMin(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsRotaryLimitJoint(constraint), "Constraint is not a rotary limit joint.");
+	return ((cpRotaryLimitJoint *)constraint)->min;
+}
+
+void
+cpRotaryLimitJointSetMin(cpConstraint *constraint, cpFloat min)
+{
+	cpAssertHard(cpConstraintIsRotaryLimitJoint(constraint), "Constraint is not a rotary limit joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpRotaryLimitJoint *)constraint)->min = min;
+}
+
+cpFloat
+cpRotaryLimitJointGetMax(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsRotaryLimitJoint(constraint), "Constraint is not a rotary limit joint.");
+	return ((cpRotaryLimitJoint *)constraint)->max;
+}
+
+void
+cpRotaryLimitJointSetMax(cpConstraint *constraint, cpFloat max)
+{
+	cpAssertHard(cpConstraintIsRotaryLimitJoint(constraint), "Constraint is not a rotary limit joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpRotaryLimitJoint *)constraint)->max = max;
+}
diff --git a/Chipmunk2D-7.0.2/src/cpShape.c b/Chipmunk2D-7.0.2/src/cpShape.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpShape.c
@@ -0,0 +1,603 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+#include "chipmunk/chipmunk_unsafe.h"
+
+#define CP_DefineShapeGetter(struct, type, member, name) \
+CP_DeclareShapeGetter(struct, type, name){ \
+	cpAssertHard(shape->klass == &struct##Class, "shape is not a "#struct); \
+	return ((struct *)shape)->member; \
+}
+
+cpShape *
+cpShapeInit(cpShape *shape, const cpShapeClass *klass, cpBody *body, struct cpShapeMassInfo massInfo)
+{
+	shape->klass = klass;
+	
+	shape->body = body;
+	shape->massInfo = massInfo;
+	
+	shape->sensor = 0;
+	
+	shape->e = 0.0f;
+	shape->u = 0.0f;
+	shape->surfaceV = cpvzero;
+	
+	shape->type = 0;
+	shape->filter.group = CP_NO_GROUP;
+	shape->filter.categories = CP_ALL_CATEGORIES;
+	shape->filter.mask = CP_ALL_CATEGORIES;
+	
+	shape->userData = NULL;
+	
+	shape->space = NULL;
+	
+	shape->next = NULL;
+	shape->prev = NULL;
+	
+	return shape;
+}
+
+void
+cpShapeDestroy(cpShape *shape)
+{
+	if(shape->klass && shape->klass->destroy) shape->klass->destroy(shape);
+}
+
+void
+cpShapeFree(cpShape *shape)
+{
+	if(shape){
+		cpShapeDestroy(shape);
+		cpfree(shape);
+	}
+}
+
+cpSpace *
+cpShapeGetSpace(const cpShape *shape)
+{
+	return shape->space;
+}
+
+cpBody *
+cpShapeGetBody(const cpShape *shape)
+{
+	return shape->body;
+}
+
+void
+cpShapeSetBody(cpShape *shape, cpBody *body)
+{
+	cpAssertHard(!cpShapeActive(shape), "You cannot change the body on an active shape. You must remove the shape from the space before changing the body.");
+	shape->body = body;
+}
+
+cpFloat cpShapeGetMass(cpShape *shape){ return shape->massInfo.m; }
+
+void
+cpShapeSetMass(cpShape *shape, cpFloat mass){
+	cpBody *body = shape->body;
+	cpBodyActivate(body);
+	
+	shape->massInfo.m = mass;
+	cpBodyAccumulateMassFromShapes(body);
+}
+
+cpFloat cpShapeGetDensity(cpShape *shape){ return shape->massInfo.m/shape->massInfo.area; }
+void cpShapeSetDensity(cpShape *shape, cpFloat density){ cpShapeSetMass(shape, density*shape->massInfo.area); }
+
+cpFloat cpShapeGetMoment(cpShape *shape){ return shape->massInfo.m*shape->massInfo.i; }
+cpFloat cpShapeGetArea(cpShape *shape){ return shape->massInfo.area; }
+cpVect cpShapeGetCenterOfGravity(cpShape *shape) { return shape->massInfo.cog; }
+
+cpBB
+cpShapeGetBB(const cpShape *shape)
+{
+	return shape->bb;
+}
+
+cpBool
+cpShapeGetSensor(const cpShape *shape)
+{
+	return shape->sensor;
+}
+
+void
+cpShapeSetSensor(cpShape *shape, cpBool sensor)
+{
+	cpBodyActivate(shape->body);
+	shape->sensor = sensor;
+}
+
+cpFloat
+cpShapeGetElasticity(const cpShape *shape)
+{
+	return shape->e;
+}
+
+void
+cpShapeSetElasticity(cpShape *shape, cpFloat elasticity)
+{
+	cpAssertHard(elasticity >= 0.0f, "Elasticity must be positive.");
+	cpBodyActivate(shape->body);
+	shape->e = elasticity;
+}
+
+cpFloat
+cpShapeGetFriction(const cpShape *shape)
+{
+	return shape->u;
+}
+
+void
+cpShapeSetFriction(cpShape *shape, cpFloat friction)
+{
+	cpAssertHard(friction >= 0.0f, "Friction must be postive.");
+	cpBodyActivate(shape->body);
+	shape->u = friction;
+}
+
+cpVect
+cpShapeGetSurfaceVelocity(const cpShape *shape)
+{
+	return shape->surfaceV;
+}
+
+void
+cpShapeSetSurfaceVelocity(cpShape *shape, cpVect surfaceVelocity)
+{
+	cpBodyActivate(shape->body);
+	shape->surfaceV = surfaceVelocity;
+}
+
+cpDataPointer
+cpShapeGetUserData(const cpShape *shape)
+{
+	return shape->userData;
+}
+
+void
+cpShapeSetUserData(cpShape *shape, cpDataPointer userData)
+{
+	shape->userData = userData;
+}
+
+cpCollisionType
+cpShapeGetCollisionType(const cpShape *shape)
+{
+	return shape->type;
+}
+
+void
+cpShapeSetCollisionType(cpShape *shape, cpCollisionType collisionType)
+{
+	cpBodyActivate(shape->body);
+	shape->type = collisionType;
+}
+
+cpShapeFilter
+cpShapeGetFilter(const cpShape *shape)
+{
+	return shape->filter;
+}
+
+void
+cpShapeSetFilter(cpShape *shape, cpShapeFilter filter)
+{
+	cpBodyActivate(shape->body);
+	shape->filter = filter;
+}
+
+cpBB
+cpShapeCacheBB(cpShape *shape)
+{
+	return cpShapeUpdate(shape, shape->body->transform);
+}
+
+cpBB
+cpShapeUpdate(cpShape *shape, cpTransform transform)
+{
+	return (shape->bb = shape->klass->cacheData(shape, transform));
+}
+
+cpFloat
+cpShapePointQuery(const cpShape *shape, cpVect p, cpPointQueryInfo *info)
+{
+	cpPointQueryInfo blank = {NULL, cpvzero, INFINITY, cpvzero};
+	if(info){
+		(*info) = blank;
+	} else {
+		info = &blank;
+	}
+	
+	shape->klass->pointQuery(shape, p, info);
+	return info->distance;
+}
+
+
+cpBool
+cpShapeSegmentQuery(const cpShape *shape, cpVect a, cpVect b, cpFloat radius, cpSegmentQueryInfo *info){
+	cpSegmentQueryInfo blank = {NULL, b, cpvzero, 1.0f};
+	if(info){
+		(*info) = blank;
+	} else {
+		info = &blank;
+	}
+	
+	cpPointQueryInfo nearest;
+	shape->klass->pointQuery(shape, a, &nearest);
+	if(nearest.distance <= radius){
+		info->shape = shape;
+		info->alpha = 0.0;
+		info->normal = cpvnormalize(cpvsub(a, nearest.point));
+	} else {
+		shape->klass->segmentQuery(shape, a, b, radius, info);
+	}
+	
+	return (info->shape != NULL);
+}
+
+cpContactPointSet
+cpShapesCollide(const cpShape *a, const cpShape *b)
+{
+	struct cpContact contacts[CP_MAX_CONTACTS_PER_ARBITER];
+	struct cpCollisionInfo info = cpCollide(a, b, 0, contacts);
+	
+	cpContactPointSet set;
+	set.count = info.count;
+	
+	// cpCollideShapes() may have swapped the contact order. Flip the normal.
+	cpBool swapped = (a != info.a);
+	set.normal = (swapped ? cpvneg(info.n) : info.n);
+	
+	for(int i=0; i<info.count; i++){
+		// cpCollideShapesInfo() returns contacts with absolute positions.
+		cpVect p1 = contacts[i].r1;
+		cpVect p2 = contacts[i].r2;
+		
+		set.points[i].pointA = (swapped ? p2 : p1);
+		set.points[i].pointB = (swapped ? p1 : p2);
+		set.points[i].distance = cpvdot(cpvsub(p2, p1), set.normal);
+	}
+	
+	return set;
+}
+
+cpCircleShape *
+cpCircleShapeAlloc(void)
+{
+	return (cpCircleShape *)cpcalloc(1, sizeof(cpCircleShape));
+}
+
+static cpBB
+cpCircleShapeCacheData(cpCircleShape *circle, cpTransform transform)
+{
+	cpVect c = circle->tc = cpTransformPoint(transform, circle->c);
+	return cpBBNewForCircle(c, circle->r);
+}
+
+static void
+cpCircleShapePointQuery(cpCircleShape *circle, cpVect p, cpPointQueryInfo *info)
+{
+	cpVect delta = cpvsub(p, circle->tc);
+	cpFloat d = cpvlength(delta);
+	cpFloat r = circle->r;
+	
+	info->shape = (cpShape *)circle;
+	info->point = cpvadd(circle->tc, cpvmult(delta, r/d)); // TODO: div/0
+	info->distance = d - r;
+	
+	// Use up for the gradient if the distance is very small.
+	info->gradient = (d > MAGIC_EPSILON ? cpvmult(delta, 1.0f/d) : cpv(0.0f, 1.0f));
+}
+
+static void
+cpCircleShapeSegmentQuery(cpCircleShape *circle, cpVect a, cpVect b, cpFloat radius, cpSegmentQueryInfo *info)
+{
+	CircleSegmentQuery((cpShape *)circle, circle->tc, circle->r, a, b, radius, info);
+}
+
+static struct cpShapeMassInfo
+cpCircleShapeMassInfo(cpFloat mass, cpFloat radius, cpVect center)
+{
+	struct cpShapeMassInfo info = {
+		mass, cpMomentForCircle(1.0f, 0.0f, radius, cpvzero),
+		center,
+		cpAreaForCircle(0.0f, radius),
+	};
+	
+	return info;
+}
+
+static const cpShapeClass cpCircleShapeClass = {
+	CP_CIRCLE_SHAPE,
+	(cpShapeCacheDataImpl)cpCircleShapeCacheData,
+	NULL,
+	(cpShapePointQueryImpl)cpCircleShapePointQuery,
+	(cpShapeSegmentQueryImpl)cpCircleShapeSegmentQuery,
+};
+
+cpCircleShape *
+cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset)
+{
+	circle->c = offset;
+	circle->r = radius;
+	
+	cpShapeInit((cpShape *)circle, &cpCircleShapeClass, body, cpCircleShapeMassInfo(0.0f, radius, offset));
+	
+	return circle;
+}
+
+cpShape *
+cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset)
+{
+	return (cpShape *)cpCircleShapeInit(cpCircleShapeAlloc(), body, radius, offset);
+}
+
+cpVect
+cpCircleShapeGetOffset(const cpShape *shape)
+{
+	cpAssertHard(shape->klass == &cpCircleShapeClass, "Shape is not a circle shape.");
+	return ((cpCircleShape *)shape)->c;
+}
+
+cpFloat
+cpCircleShapeGetRadius(const cpShape *shape)
+{
+	cpAssertHard(shape->klass == &cpCircleShapeClass, "Shape is not a circle shape.");
+	return ((cpCircleShape *)shape)->r;
+}
+
+
+cpSegmentShape *
+cpSegmentShapeAlloc(void)
+{
+	return (cpSegmentShape *)cpcalloc(1, sizeof(cpSegmentShape));
+}
+
+static cpBB
+cpSegmentShapeCacheData(cpSegmentShape *seg, cpTransform transform)
+{
+	seg->ta = cpTransformPoint(transform, seg->a);
+	seg->tb = cpTransformPoint(transform, seg->b);
+	seg->tn = cpTransformVect(transform, seg->n);
+	
+	cpFloat l,r,b,t;
+	
+	if(seg->ta.x < seg->tb.x){
+		l = seg->ta.x;
+		r = seg->tb.x;
+	} else {
+		l = seg->tb.x;
+		r = seg->ta.x;
+	}
+	
+	if(seg->ta.y < seg->tb.y){
+		b = seg->ta.y;
+		t = seg->tb.y;
+	} else {
+		b = seg->tb.y;
+		t = seg->ta.y;
+	}
+	
+	cpFloat rad = seg->r;
+	return cpBBNew(l - rad, b - rad, r + rad, t + rad);
+}
+
+static void
+cpSegmentShapePointQuery(cpSegmentShape *seg, cpVect p, cpPointQueryInfo *info)
+{
+	cpVect closest = cpClosetPointOnSegment(p, seg->ta, seg->tb);
+	
+	cpVect delta = cpvsub(p, closest);
+	cpFloat d = cpvlength(delta);
+	cpFloat r = seg->r;
+	cpVect g = cpvmult(delta, 1.0f/d);
+	
+	info->shape = (cpShape *)seg;
+	info->point = (d ? cpvadd(closest, cpvmult(g, r)) : closest);
+	info->distance = d - r;
+	
+	// Use the segment's normal if the distance is very small.
+	info->gradient = (d > MAGIC_EPSILON ? g : seg->n);
+}
+
+static void
+cpSegmentShapeSegmentQuery(cpSegmentShape *seg, cpVect a, cpVect b, cpFloat r2, cpSegmentQueryInfo *info)
+{
+	cpVect n = seg->tn;
+	cpFloat d = cpvdot(cpvsub(seg->ta, a), n);
+	cpFloat r = seg->r + r2;
+	
+	cpVect flipped_n = (d > 0.0f ? cpvneg(n) : n);
+	cpVect seg_offset = cpvsub(cpvmult(flipped_n, r), a);
+	
+	// Make the endpoints relative to 'a' and move them by the thickness of the segment.
+	cpVect seg_a = cpvadd(seg->ta, seg_offset);
+	cpVect seg_b = cpvadd(seg->tb, seg_offset);
+	cpVect delta = cpvsub(b, a);
+	
+	if(cpvcross(delta, seg_a)*cpvcross(delta, seg_b) <= 0.0f){
+		cpFloat d_offset = d + (d > 0.0f ? -r : r);
+		cpFloat ad = -d_offset;
+		cpFloat bd = cpvdot(delta, n) - d_offset;
+		
+		if(ad*bd < 0.0f){
+			cpFloat t = ad/(ad - bd);
+			
+			info->shape = (cpShape *)seg;
+			info->point = cpvsub(cpvlerp(a, b, t), cpvmult(flipped_n, r2));
+			info->normal = flipped_n;
+			info->alpha = t;
+		}
+	} else if(r != 0.0f){
+		cpSegmentQueryInfo info1 = {NULL, b, cpvzero, 1.0f};
+		cpSegmentQueryInfo info2 = {NULL, b, cpvzero, 1.0f};
+		CircleSegmentQuery((cpShape *)seg, seg->ta, seg->r, a, b, r2, &info1);
+		CircleSegmentQuery((cpShape *)seg, seg->tb, seg->r, a, b, r2, &info2);
+		
+		if(info1.alpha < info2.alpha){
+			(*info) = info1;
+		} else {
+			(*info) = info2;
+		}
+	}
+}
+
+static struct cpShapeMassInfo
+cpSegmentShapeMassInfo(cpFloat mass, cpVect a, cpVect b, cpFloat r)
+{
+	struct cpShapeMassInfo info = {
+		mass, cpMomentForBox(1.0f, cpvdist(a, b) + 2.0f*r, 2.0f*r), // TODO is an approximation.
+		cpvlerp(a, b, 0.5f),
+		cpAreaForSegment(a, b, r),
+	};
+	
+	return info;
+}
+
+static const cpShapeClass cpSegmentShapeClass = {
+	CP_SEGMENT_SHAPE,
+	(cpShapeCacheDataImpl)cpSegmentShapeCacheData,
+	NULL,
+	(cpShapePointQueryImpl)cpSegmentShapePointQuery,
+	(cpShapeSegmentQueryImpl)cpSegmentShapeSegmentQuery,
+};
+
+cpSegmentShape *
+cpSegmentShapeInit(cpSegmentShape *seg, cpBody *body, cpVect a, cpVect b, cpFloat r)
+{
+	seg->a = a;
+	seg->b = b;
+	seg->n = cpvrperp(cpvnormalize(cpvsub(b, a)));
+	
+	seg->r = r;
+	
+	seg->a_tangent = cpvzero;
+	seg->b_tangent = cpvzero;
+	
+	cpShapeInit((cpShape *)seg, &cpSegmentShapeClass, body, cpSegmentShapeMassInfo(0.0f, a, b, r));
+	
+	return seg;
+}
+
+cpShape*
+cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat r)
+{
+	return (cpShape *)cpSegmentShapeInit(cpSegmentShapeAlloc(), body, a, b, r);
+}
+
+cpVect
+cpSegmentShapeGetA(const cpShape *shape)
+{
+	cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");
+	return ((cpSegmentShape *)shape)->a;
+}
+
+cpVect
+cpSegmentShapeGetB(const cpShape *shape)
+{
+	cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");
+	return ((cpSegmentShape *)shape)->b;
+}
+
+cpVect
+cpSegmentShapeGetNormal(const cpShape *shape)
+{
+	cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");
+	return ((cpSegmentShape *)shape)->n;
+}
+
+cpFloat
+cpSegmentShapeGetRadius(const cpShape *shape)
+{
+	cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");
+	return ((cpSegmentShape *)shape)->r;
+}
+
+void
+cpSegmentShapeSetNeighbors(cpShape *shape, cpVect prev, cpVect next)
+{
+	cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");
+	cpSegmentShape *seg = (cpSegmentShape *)shape;
+	
+	seg->a_tangent = cpvsub(prev, seg->a);
+	seg->b_tangent = cpvsub(next, seg->b);
+}
+
+// Unsafe API (chipmunk_unsafe.h)
+
+// TODO setters should wake the shape up?
+
+void
+cpCircleShapeSetRadius(cpShape *shape, cpFloat radius)
+{
+	cpAssertHard(shape->klass == &cpCircleShapeClass, "Shape is not a circle shape.");
+	cpCircleShape *circle = (cpCircleShape *)shape;
+	
+	circle->r = radius;
+	
+	cpFloat mass = shape->massInfo.m;
+	shape->massInfo = cpCircleShapeMassInfo(mass, circle->r, circle->c);
+	if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body);
+}
+
+void
+cpCircleShapeSetOffset(cpShape *shape, cpVect offset)
+{
+	cpAssertHard(shape->klass == &cpCircleShapeClass, "Shape is not a circle shape.");
+	cpCircleShape *circle = (cpCircleShape *)shape;
+	
+	circle->c = offset;
+
+	cpFloat mass = shape->massInfo.m;
+	shape->massInfo = cpCircleShapeMassInfo(shape->massInfo.m, circle->r, circle->c);
+	if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body);
+}
+
+void
+cpSegmentShapeSetEndpoints(cpShape *shape, cpVect a, cpVect b)
+{
+	cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");
+	cpSegmentShape *seg = (cpSegmentShape *)shape;
+	
+	seg->a = a;
+	seg->b = b;
+	seg->n = cpvperp(cpvnormalize(cpvsub(b, a)));
+
+	cpFloat mass = shape->massInfo.m;
+	shape->massInfo = cpSegmentShapeMassInfo(shape->massInfo.m, seg->a, seg->b, seg->r);
+	if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body);
+}
+
+void
+cpSegmentShapeSetRadius(cpShape *shape, cpFloat radius)
+{
+	cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");
+	cpSegmentShape *seg = (cpSegmentShape *)shape;
+	
+	seg->r = radius;
+
+	cpFloat mass = shape->massInfo.m;
+	shape->massInfo = cpSegmentShapeMassInfo(shape->massInfo.m, seg->a, seg->b, seg->r);
+	if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body);
+}
diff --git a/Chipmunk2D-7.0.2/src/cpSimpleMotor.c b/Chipmunk2D-7.0.2/src/cpSimpleMotor.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpSimpleMotor.c
@@ -0,0 +1,123 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpSimpleMotor *joint, cpFloat dt)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	// calculate moment of inertia coefficient.
+	joint->iSum = 1.0f/(a->i_inv + b->i_inv);
+}
+
+static void
+applyCachedImpulse(cpSimpleMotor *joint, cpFloat dt_coef)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	cpFloat j = joint->jAcc*dt_coef;
+	a->w -= j*a->i_inv;
+	b->w += j*b->i_inv;
+}
+
+static void
+applyImpulse(cpSimpleMotor *joint, cpFloat dt)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	// compute relative rotational velocity
+	cpFloat wr = b->w - a->w + joint->rate;
+	
+	cpFloat jMax = joint->constraint.maxForce*dt;
+	
+	// compute normal impulse	
+	cpFloat j = -wr*joint->iSum;
+	cpFloat jOld = joint->jAcc;
+	joint->jAcc = cpfclamp(jOld + j, -jMax, jMax);
+	j = joint->jAcc - jOld;
+	
+	// apply impulse
+	a->w -= j*a->i_inv;
+	b->w += j*b->i_inv;
+}
+
+static cpFloat
+getImpulse(cpSimpleMotor *joint)
+{
+	return cpfabs(joint->jAcc);
+}
+
+static const cpConstraintClass klass = {
+	(cpConstraintPreStepImpl)preStep,
+	(cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+	(cpConstraintApplyImpulseImpl)applyImpulse,
+	(cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpSimpleMotor *
+cpSimpleMotorAlloc(void)
+{
+	return (cpSimpleMotor *)cpcalloc(1, sizeof(cpSimpleMotor));
+}
+
+cpSimpleMotor *
+cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate)
+{
+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+	
+	joint->rate = rate;
+	
+	joint->jAcc = 0.0f;
+	
+	return joint;
+}
+
+cpConstraint *
+cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate)
+{
+	return (cpConstraint *)cpSimpleMotorInit(cpSimpleMotorAlloc(), a, b, rate);
+}
+
+cpBool
+cpConstraintIsSimpleMotor(const cpConstraint *constraint)
+{
+	return (constraint->klass == &klass);
+}
+
+cpFloat
+cpSimpleMotorGetRate(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsSimpleMotor(constraint), "Constraint is not a pin joint.");
+	return ((cpSimpleMotor *)constraint)->rate;
+}
+
+void
+cpSimpleMotorSetRate(cpConstraint *constraint, cpFloat rate)
+{
+	cpAssertHard(cpConstraintIsSimpleMotor(constraint), "Constraint is not a pin joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpSimpleMotor *)constraint)->rate = rate;
+}
diff --git a/Chipmunk2D-7.0.2/src/cpSlideJoint.c b/Chipmunk2D-7.0.2/src/cpSlideJoint.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpSlideJoint.c
@@ -0,0 +1,195 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpSlideJoint *joint, cpFloat dt)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	joint->r1 = cpTransformVect(a->transform, cpvsub(joint->anchorA, a->cog));
+	joint->r2 = cpTransformVect(b->transform, cpvsub(joint->anchorB, b->cog));
+	
+	cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
+	cpFloat dist = cpvlength(delta);
+	cpFloat pdist = 0.0f;
+	if(dist > joint->max) {
+		pdist = dist - joint->max;
+		joint->n = cpvnormalize(delta);
+	} else if(dist < joint->min) {
+		pdist = joint->min - dist;
+		joint->n = cpvneg(cpvnormalize(delta));
+	} else {
+		joint->n = cpvzero;
+		joint->jnAcc = 0.0f;
+	}
+	
+	// calculate mass normal
+	joint->nMass = 1.0f/k_scalar(a, b, joint->r1, joint->r2, joint->n);
+	
+	// calculate bias velocity
+	cpFloat maxBias = joint->constraint.maxBias;
+	joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias);
+}
+
+static void
+applyCachedImpulse(cpSlideJoint *joint, cpFloat dt_coef)
+{
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	cpVect j = cpvmult(joint->n, joint->jnAcc*dt_coef);
+	apply_impulses(a, b, joint->r1, joint->r2, j);
+}
+
+static void
+applyImpulse(cpSlideJoint *joint, cpFloat dt)
+{
+	if(cpveql(joint->n, cpvzero)) return;  // early exit
+
+	cpBody *a = joint->constraint.a;
+	cpBody *b = joint->constraint.b;
+	
+	cpVect n = joint->n;
+	cpVect r1 = joint->r1;
+	cpVect r2 = joint->r2;
+		
+	// compute relative velocity
+	cpVect vr = relative_velocity(a, b, r1, r2);
+	cpFloat vrn = cpvdot(vr, n);
+	
+	// compute normal impulse
+	cpFloat jn = (joint->bias - vrn)*joint->nMass;
+	cpFloat jnOld = joint->jnAcc;
+	joint->jnAcc = cpfclamp(jnOld + jn, -joint->constraint.maxForce*dt, 0.0f);
+	jn = joint->jnAcc - jnOld;
+	
+	// apply impulse
+	apply_impulses(a, b, joint->r1, joint->r2, cpvmult(n, jn));
+}
+
+static cpFloat
+getImpulse(cpConstraint *joint)
+{
+	return cpfabs(((cpSlideJoint *)joint)->jnAcc);
+}
+
+static const cpConstraintClass klass = {
+	(cpConstraintPreStepImpl)preStep,
+	(cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+	(cpConstraintApplyImpulseImpl)applyImpulse,
+	(cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpSlideJoint *
+cpSlideJointAlloc(void)
+{
+	return (cpSlideJoint *)cpcalloc(1, sizeof(cpSlideJoint));
+}
+
+cpSlideJoint *
+cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat min, cpFloat max)
+{
+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+	
+	joint->anchorA = anchorA;
+	joint->anchorB = anchorB;
+	joint->min = min;
+	joint->max = max;
+	
+	joint->jnAcc = 0.0f;
+	
+	return joint;
+}
+
+cpConstraint *
+cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat min, cpFloat max)
+{
+	return (cpConstraint *)cpSlideJointInit(cpSlideJointAlloc(), a, b, anchorA, anchorB, min, max);
+}
+
+cpBool
+cpConstraintIsSlideJoint(const cpConstraint *constraint)
+{
+	return (constraint->klass == &klass);
+}
+
+cpVect
+cpSlideJointGetAnchorA(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+	return ((cpSlideJoint *)constraint)->anchorA;
+}
+
+void
+cpSlideJointSetAnchorA(cpConstraint *constraint, cpVect anchorA)
+{
+	cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpSlideJoint *)constraint)->anchorA = anchorA;
+}
+
+cpVect
+cpSlideJointGetAnchorB(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+	return ((cpSlideJoint *)constraint)->anchorB;
+}
+
+void
+cpSlideJointSetAnchorB(cpConstraint *constraint, cpVect anchorB)
+{
+	cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpSlideJoint *)constraint)->anchorB = anchorB;
+}
+
+cpFloat
+cpSlideJointGetMin(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+	return ((cpSlideJoint *)constraint)->min;
+}
+
+void
+cpSlideJointSetMin(cpConstraint *constraint, cpFloat min)
+{
+	cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpSlideJoint *)constraint)->min = min;
+}
+
+cpFloat
+cpSlideJointGetMax(const cpConstraint *constraint)
+{
+	cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+	return ((cpSlideJoint *)constraint)->max;
+}
+
+void
+cpSlideJointSetMax(cpConstraint *constraint, cpFloat max)
+{
+	cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+	cpConstraintActivateBodies(constraint);
+	((cpSlideJoint *)constraint)->max = max;
+}
diff --git a/Chipmunk2D-7.0.2/src/cpSpace.c b/Chipmunk2D-7.0.2/src/cpSpace.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpSpace.c
@@ -0,0 +1,700 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "chipmunk/chipmunk_private.h"
+
+//MARK: Contact Set Helpers
+
+// Equal function for arbiterSet.
+static cpBool
+arbiterSetEql(cpShape **shapes, cpArbiter *arb)
+{
+	cpShape *a = shapes[0];
+	cpShape *b = shapes[1];
+	
+	return ((a == arb->a && b == arb->b) || (b == arb->a && a == arb->b));
+}
+
+//MARK: Collision Handler Set HelperFunctions
+
+// Equals function for collisionHandlers.
+static cpBool
+handlerSetEql(cpCollisionHandler *check, cpCollisionHandler *pair)
+{
+	return (
+		(check->typeA == pair->typeA && check->typeB == pair->typeB) ||
+		(check->typeB == pair->typeA && check->typeA == pair->typeB)
+	);
+}
+
+// Transformation function for collisionHandlers.
+static void *
+handlerSetTrans(cpCollisionHandler *handler, void *unused)
+{
+	cpCollisionHandler *copy = (cpCollisionHandler *)cpcalloc(1, sizeof(cpCollisionHandler));
+	memcpy(copy, handler, sizeof(cpCollisionHandler));
+	
+	return copy;
+}
+
+//MARK: Misc Helper Funcs
+
+// Default collision functions.
+
+static cpBool
+DefaultBegin(cpArbiter *arb, cpSpace *space, void *data){
+	cpBool retA = cpArbiterCallWildcardBeginA(arb, space);
+	cpBool retB = cpArbiterCallWildcardBeginB(arb, space);
+	return retA && retB;
+}
+
+static cpBool
+DefaultPreSolve(cpArbiter *arb, cpSpace *space, void *data){
+	cpBool retA = cpArbiterCallWildcardPreSolveA(arb, space);
+	cpBool retB = cpArbiterCallWildcardPreSolveB(arb, space);
+	return retA && retB;
+}
+
+static void
+DefaultPostSolve(cpArbiter *arb, cpSpace *space, void *data){
+	cpArbiterCallWildcardPostSolveA(arb, space);
+	cpArbiterCallWildcardPostSolveB(arb, space);
+}
+
+static void
+DefaultSeparate(cpArbiter *arb, cpSpace *space, void *data){
+	cpArbiterCallWildcardSeparateA(arb, space);
+	cpArbiterCallWildcardSeparateB(arb, space);
+}
+
+// Use the wildcard identifier since  the default handler should never match any type pair.
+static cpCollisionHandler cpCollisionHandlerDefault = {
+	CP_WILDCARD_COLLISION_TYPE, CP_WILDCARD_COLLISION_TYPE,
+	DefaultBegin, DefaultPreSolve, DefaultPostSolve, DefaultSeparate, NULL
+};
+
+static cpBool AlwaysCollide(cpArbiter *arb, cpSpace *space, void *data){return cpTrue;}
+static void DoNothing(cpArbiter *arb, cpSpace *space, void *data){}
+
+cpCollisionHandler cpCollisionHandlerDoNothing = {
+	CP_WILDCARD_COLLISION_TYPE, CP_WILDCARD_COLLISION_TYPE,
+	AlwaysCollide, AlwaysCollide, DoNothing, DoNothing, NULL
+};
+
+// function to get the estimated velocity of a shape for the cpBBTree.
+static cpVect ShapeVelocityFunc(cpShape *shape){return shape->body->v;}
+
+// Used for disposing of collision handlers.
+static void FreeWrap(void *ptr, void *unused){cpfree(ptr);}
+
+//MARK: Memory Management Functions
+
+cpSpace *
+cpSpaceAlloc(void)
+{
+	return (cpSpace *)cpcalloc(1, sizeof(cpSpace));
+}
+
+cpSpace*
+cpSpaceInit(cpSpace *space)
+{
+#ifndef NDEBUG
+	static cpBool done = cpFalse;
+	if(!done){
+		printf("Initializing cpSpace - Chipmunk v%s (Debug Enabled)\n", cpVersionString);
+		printf("Compile with -DNDEBUG defined to disable debug mode and runtime assertion checks\n");
+		done = cpTrue;
+	}
+#endif
+
+	space->iterations = 10;
+	
+	space->gravity = cpvzero;
+	space->damping = 1.0f;
+	
+	space->collisionSlop = 0.1f;
+	space->collisionBias = cpfpow(1.0f - 0.1f, 60.0f);
+	space->collisionPersistence = 3;
+	
+	space->locked = 0;
+	space->stamp = 0;
+	
+	space->shapeIDCounter = 0;
+	space->staticShapes = cpBBTreeNew((cpSpatialIndexBBFunc)cpShapeGetBB, NULL);
+	space->dynamicShapes = cpBBTreeNew((cpSpatialIndexBBFunc)cpShapeGetBB, space->staticShapes);
+	cpBBTreeSetVelocityFunc(space->dynamicShapes, (cpBBTreeVelocityFunc)ShapeVelocityFunc);
+	
+	space->allocatedBuffers = cpArrayNew(0);
+	
+	space->dynamicBodies = cpArrayNew(0);
+	space->staticBodies = cpArrayNew(0);
+	space->sleepingComponents = cpArrayNew(0);
+	space->rousedBodies = cpArrayNew(0);
+	
+	space->sleepTimeThreshold = INFINITY;
+	space->idleSpeedThreshold = 0.0f;
+	
+	space->arbiters = cpArrayNew(0);
+	space->pooledArbiters = cpArrayNew(0);
+	
+	space->contactBuffersHead = NULL;
+	space->cachedArbiters = cpHashSetNew(0, (cpHashSetEqlFunc)arbiterSetEql);
+	
+	space->constraints = cpArrayNew(0);
+	
+	space->usesWildcards = cpFalse;
+	memcpy(&space->defaultHandler, &cpCollisionHandlerDoNothing, sizeof(cpCollisionHandler));
+	space->collisionHandlers = cpHashSetNew(0, (cpHashSetEqlFunc)handlerSetEql);
+	
+	space->postStepCallbacks = cpArrayNew(0);
+	space->skipPostStep = cpFalse;
+	
+	cpBody *staticBody = cpBodyInit(&space->_staticBody, 0.0f, 0.0f);
+	cpBodySetType(staticBody, CP_BODY_TYPE_STATIC);
+	cpSpaceSetStaticBody(space, staticBody);
+	
+	return space;
+}
+
+cpSpace*
+cpSpaceNew(void)
+{
+	return cpSpaceInit(cpSpaceAlloc());
+}
+
+static void cpBodyActivateWrap(cpBody *body, void *unused){cpBodyActivate(body);}
+
+void
+cpSpaceDestroy(cpSpace *space)
+{
+	cpSpaceEachBody(space, (cpSpaceBodyIteratorFunc)cpBodyActivateWrap, NULL);
+	
+	cpSpatialIndexFree(space->staticShapes);
+	cpSpatialIndexFree(space->dynamicShapes);
+	
+	cpArrayFree(space->dynamicBodies);
+	cpArrayFree(space->staticBodies);
+	cpArrayFree(space->sleepingComponents);
+	cpArrayFree(space->rousedBodies);
+	
+	cpArrayFree(space->constraints);
+	
+	cpHashSetFree(space->cachedArbiters);
+	
+	cpArrayFree(space->arbiters);
+	cpArrayFree(space->pooledArbiters);
+	
+	if(space->allocatedBuffers){
+		cpArrayFreeEach(space->allocatedBuffers, cpfree);
+		cpArrayFree(space->allocatedBuffers);
+	}
+	
+	if(space->postStepCallbacks){
+		cpArrayFreeEach(space->postStepCallbacks, cpfree);
+		cpArrayFree(space->postStepCallbacks);
+	}
+	
+	if(space->collisionHandlers) cpHashSetEach(space->collisionHandlers, FreeWrap, NULL);
+	cpHashSetFree(space->collisionHandlers);
+}
+
+void
+cpSpaceFree(cpSpace *space)
+{
+	if(space){
+		cpSpaceDestroy(space);
+		cpfree(space);
+	}
+}
+
+
+//MARK: Basic properties:
+
+int
+cpSpaceGetIterations(const cpSpace *space)
+{
+	return space->iterations;
+}
+
+void
+cpSpaceSetIterations(cpSpace *space, int iterations)
+{
+	cpAssertHard(iterations > 0, "Iterations must be positive and non-zero.");
+	space->iterations = iterations;
+}
+
+cpVect
+cpSpaceGetGravity(const cpSpace *space)
+{
+	return space->gravity;
+}
+
+void
+cpSpaceSetGravity(cpSpace *space, cpVect gravity)
+{
+	space->gravity = gravity;
+	
+	// Wake up all of the bodies since the gravity changed.
+	cpArray *components = space->sleepingComponents;
+	for(int i=0; i<components->num; i++){
+		cpBodyActivate((cpBody *)components->arr[i]);
+	}
+}
+
+cpFloat
+cpSpaceGetDamping(const cpSpace *space)
+{
+	return space->damping;
+}
+
+void
+cpSpaceSetDamping(cpSpace *space, cpFloat damping)
+{
+	cpAssertHard(damping >= 0.0, "Damping must be positive.");
+	space->damping = damping;
+}
+
+cpFloat
+cpSpaceGetIdleSpeedThreshold(const cpSpace *space)
+{
+	return space->idleSpeedThreshold;
+}
+
+void
+cpSpaceSetIdleSpeedThreshold(cpSpace *space, cpFloat idleSpeedThreshold)
+{
+	space->idleSpeedThreshold = idleSpeedThreshold;
+}
+
+cpFloat
+cpSpaceGetSleepTimeThreshold(const cpSpace *space)
+{
+	return space->sleepTimeThreshold;
+}
+
+void
+cpSpaceSetSleepTimeThreshold(cpSpace *space, cpFloat sleepTimeThreshold)
+{
+	space->sleepTimeThreshold = sleepTimeThreshold;
+}
+
+cpFloat
+cpSpaceGetCollisionSlop(const cpSpace *space)
+{
+	return space->collisionSlop;
+}
+
+void
+cpSpaceSetCollisionSlop(cpSpace *space, cpFloat collisionSlop)
+{
+	space->collisionSlop = collisionSlop;
+}
+
+cpFloat
+cpSpaceGetCollisionBias(const cpSpace *space)
+{
+	return space->collisionBias;
+}
+
+void
+cpSpaceSetCollisionBias(cpSpace *space, cpFloat collisionBias)
+{
+	space->collisionBias = collisionBias;
+}
+
+cpTimestamp
+cpSpaceGetCollisionPersistence(const cpSpace *space)
+{
+	return space->collisionPersistence;
+}
+
+void
+cpSpaceSetCollisionPersistence(cpSpace *space, cpTimestamp collisionPersistence)
+{
+	space->collisionPersistence = collisionPersistence;
+}
+
+cpDataPointer
+cpSpaceGetUserData(const cpSpace *space)
+{
+	return space->userData;
+}
+
+void
+cpSpaceSetUserData(cpSpace *space, cpDataPointer userData)
+{
+	space->userData = userData;
+}
+
+cpBody *
+cpSpaceGetStaticBody(const cpSpace *space)
+{
+	return space->staticBody;
+}
+
+cpFloat
+cpSpaceGetCurrentTimeStep(const cpSpace *space)
+{
+	return space->curr_dt;
+}
+
+void
+cpSpaceSetStaticBody(cpSpace *space, cpBody *body)
+{
+	if(space->staticBody != NULL){
+		cpAssertHard(space->staticBody->shapeList == NULL, "Internal Error: Changing the designated static body while the old one still had shapes attached.");
+		space->staticBody->space = NULL;
+	}
+	
+	space->staticBody = body;
+	body->space = space;
+}
+
+cpBool
+cpSpaceIsLocked(cpSpace *space)
+{
+	return (space->locked > 0);
+}
+
+//MARK: Collision Handler Function Management
+
+static void
+cpSpaceUseWildcardDefaultHandler(cpSpace *space)
+{
+	// Spaces default to using the slightly faster "do nothing" default handler until wildcards are potentially needed.
+	if(!space->usesWildcards){
+		space->usesWildcards = cpTrue;
+		memcpy(&space->defaultHandler, &cpCollisionHandlerDefault, sizeof(cpCollisionHandler));
+	}
+}
+
+cpCollisionHandler *cpSpaceAddDefaultCollisionHandler(cpSpace *space)
+{
+	cpSpaceUseWildcardDefaultHandler(space);
+	return &space->defaultHandler;
+}
+
+cpCollisionHandler *cpSpaceAddCollisionHandler(cpSpace *space, cpCollisionType a, cpCollisionType b)
+{
+	cpHashValue hash = CP_HASH_PAIR(a, b);
+	cpCollisionHandler handler = {a, b, DefaultBegin, DefaultPreSolve, DefaultPostSolve, DefaultSeparate, NULL};
+	return (cpCollisionHandler*)cpHashSetInsert(space->collisionHandlers, hash, &handler, (cpHashSetTransFunc)handlerSetTrans, NULL);
+}
+
+cpCollisionHandler *
+cpSpaceAddWildcardHandler(cpSpace *space, cpCollisionType type)
+{
+	cpSpaceUseWildcardDefaultHandler(space);
+	
+	cpHashValue hash = CP_HASH_PAIR(type, CP_WILDCARD_COLLISION_TYPE);
+	cpCollisionHandler handler = {type, CP_WILDCARD_COLLISION_TYPE, AlwaysCollide, AlwaysCollide, DoNothing, DoNothing, NULL};
+	return (cpCollisionHandler*)cpHashSetInsert(space->collisionHandlers, hash, &handler, (cpHashSetTransFunc)handlerSetTrans, NULL);
+}
+
+
+//MARK: Body, Shape, and Joint Management
+cpShape *
+cpSpaceAddShape(cpSpace *space, cpShape *shape)
+{
+	cpBody *body = shape->body;
+	
+	cpAssertHard(shape->space != space, "You have already added this shape to this space. You must not add it a second time.");
+	cpAssertHard(!shape->space, "You have already added this shape to another space. You cannot add it to a second.");
+//	cpAssertHard(body->space == space, "The shape's body must be added to the space before the shape.");
+	cpAssertSpaceUnlocked(space);
+	
+	cpBool isStatic = (cpBodyGetType(body) == CP_BODY_TYPE_STATIC);
+	if(!isStatic) cpBodyActivate(body);
+	cpBodyAddShape(body, shape);
+	
+	shape->hashid = space->shapeIDCounter++;
+	cpShapeUpdate(shape, body->transform);
+	cpSpatialIndexInsert(isStatic ? space->staticShapes : space->dynamicShapes, shape, shape->hashid);
+	shape->space = space;
+		
+	return shape;
+}
+
+cpBody *
+cpSpaceAddBody(cpSpace *space, cpBody *body)
+{
+	cpAssertHard(body->space != space, "You have already added this body to this space. You must not add it a second time.");
+	cpAssertHard(!body->space, "You have already added this body to another space. You cannot add it to a second.");
+	cpAssertSpaceUnlocked(space);
+	
+	cpArrayPush(cpSpaceArrayForBodyType(space, cpBodyGetType(body)), body);
+	body->space = space;
+	
+	return body;
+}
+
+cpConstraint *
+cpSpaceAddConstraint(cpSpace *space, cpConstraint *constraint)
+{
+	cpAssertHard(constraint->space != space, "You have already added this constraint to this space. You must not add it a second time.");
+	cpAssertHard(!constraint->space, "You have already added this constraint to another space. You cannot add it to a second.");
+	cpAssertSpaceUnlocked(space);
+	
+	cpBody *a = constraint->a, *b = constraint->b;
+	cpAssertHard(a != NULL && b != NULL, "Constraint is attached to a NULL body.");
+//	cpAssertHard(a->space == space && b->space == space, "The constraint's bodies must be added to the space before the constraint.");
+	
+	cpBodyActivate(a);
+	cpBodyActivate(b);
+	cpArrayPush(space->constraints, constraint);
+	
+	// Push onto the heads of the bodies' constraint lists
+	constraint->next_a = a->constraintList; a->constraintList = constraint;
+	constraint->next_b = b->constraintList; b->constraintList = constraint;
+	constraint->space = space;
+	
+	return constraint;
+}
+
+struct arbiterFilterContext {
+	cpSpace *space;
+	cpBody *body;
+	cpShape *shape;
+};
+
+static cpBool
+cachedArbitersFilter(cpArbiter *arb, struct arbiterFilterContext *context)
+{
+	cpShape *shape = context->shape;
+	cpBody *body = context->body;
+	
+	
+	// Match on the filter shape, or if it's NULL the filter body
+	if(
+		(body == arb->body_a && (shape == arb->a || shape == NULL)) ||
+		(body == arb->body_b && (shape == arb->b || shape == NULL))
+	){
+		// Call separate when removing shapes.
+		if(shape && arb->state != CP_ARBITER_STATE_CACHED){
+			// Invalidate the arbiter since one of the shapes was removed.
+			arb->state = CP_ARBITER_STATE_INVALIDATED;
+			
+			cpCollisionHandler *handler = arb->handler;
+			handler->separateFunc(arb, context->space, handler->userData);
+		}
+		
+		cpArbiterUnthread(arb);
+		cpArrayDeleteObj(context->space->arbiters, arb);
+		cpArrayPush(context->space->pooledArbiters, arb);
+		
+		return cpFalse;
+	}
+	
+	return cpTrue;
+}
+
+void
+cpSpaceFilterArbiters(cpSpace *space, cpBody *body, cpShape *filter)
+{
+	cpSpaceLock(space); {
+		struct arbiterFilterContext context = {space, body, filter};
+		cpHashSetFilter(space->cachedArbiters, (cpHashSetFilterFunc)cachedArbitersFilter, &context);
+	} cpSpaceUnlock(space, cpTrue);
+}
+
+void
+cpSpaceRemoveShape(cpSpace *space, cpShape *shape)
+{
+	cpBody *body = shape->body;
+	cpAssertHard(cpSpaceContainsShape(space, shape), "Cannot remove a shape that was not added to the space. (Removed twice maybe?)");
+	cpAssertSpaceUnlocked(space);
+	
+	cpBool isStatic = (cpBodyGetType(body) == CP_BODY_TYPE_STATIC);
+	if(isStatic){
+		cpBodyActivateStatic(body, shape);
+	} else {
+		cpBodyActivate(body);
+	}
+
+	cpBodyRemoveShape(body, shape);
+	cpSpaceFilterArbiters(space, body, shape);
+	cpSpatialIndexRemove(isStatic ? space->staticShapes : space->dynamicShapes, shape, shape->hashid);
+	shape->space = NULL;
+	shape->hashid = 0;
+}
+
+void
+cpSpaceRemoveBody(cpSpace *space, cpBody *body)
+{
+	cpAssertHard(body != cpSpaceGetStaticBody(space), "Cannot remove the designated static body for the space.");
+	cpAssertHard(cpSpaceContainsBody(space, body), "Cannot remove a body that was not added to the space. (Removed twice maybe?)");
+//	cpAssertHard(body->shapeList == NULL, "Cannot remove a body from the space before removing the bodies attached to it.");
+//	cpAssertHard(body->constraintList == NULL, "Cannot remove a body from the space before removing the constraints attached to it.");
+	cpAssertSpaceUnlocked(space);
+	
+	cpBodyActivate(body);
+//	cpSpaceFilterArbiters(space, body, NULL);
+	cpArrayDeleteObj(cpSpaceArrayForBodyType(space, cpBodyGetType(body)), body);
+	body->space = NULL;
+}
+
+void
+cpSpaceRemoveConstraint(cpSpace *space, cpConstraint *constraint)
+{
+	cpAssertHard(cpSpaceContainsConstraint(space, constraint), "Cannot remove a constraint that was not added to the space. (Removed twice maybe?)");
+	cpAssertSpaceUnlocked(space);
+	
+	cpBodyActivate(constraint->a);
+	cpBodyActivate(constraint->b);
+	cpArrayDeleteObj(space->constraints, constraint);
+	
+	cpBodyRemoveConstraint(constraint->a, constraint);
+	cpBodyRemoveConstraint(constraint->b, constraint);
+	constraint->space = NULL;
+}
+
+cpBool cpSpaceContainsShape(cpSpace *space, cpShape *shape)
+{
+	return (shape->space == space);
+}
+
+cpBool cpSpaceContainsBody(cpSpace *space, cpBody *body)
+{
+	return (body->space == space);
+}
+
+cpBool cpSpaceContainsConstraint(cpSpace *space, cpConstraint *constraint)
+{
+	return (constraint->space == space);
+}
+
+//MARK: Iteration
+
+void
+cpSpaceEachBody(cpSpace *space, cpSpaceBodyIteratorFunc func, void *data)
+{
+	cpSpaceLock(space); {
+		cpArray *bodies = space->dynamicBodies;
+		for(int i=0; i<bodies->num; i++){
+			func((cpBody *)bodies->arr[i], data);
+		}
+		
+		cpArray *otherBodies = space->staticBodies;
+		for(int i=0; i<otherBodies->num; i++){
+			func((cpBody *)otherBodies->arr[i], data);
+		}
+		
+		cpArray *components = space->sleepingComponents;
+		for(int i=0; i<components->num; i++){
+			cpBody *root = (cpBody *)components->arr[i];
+			
+			cpBody *body = root;
+			while(body){
+				cpBody *next = body->sleeping.next;
+				func(body, data);
+				body = next;
+			}
+		}
+	} cpSpaceUnlock(space, cpTrue);
+}
+
+typedef struct spaceShapeContext {
+	cpSpaceShapeIteratorFunc func;
+	void *data;
+} spaceShapeContext;
+
+static void
+spaceEachShapeIterator(cpShape *shape, spaceShapeContext *context)
+{
+	context->func(shape, context->data);
+}
+
+void
+cpSpaceEachShape(cpSpace *space, cpSpaceShapeIteratorFunc func, void *data)
+{
+	cpSpaceLock(space); {
+		spaceShapeContext context = {func, data};
+		cpSpatialIndexEach(space->dynamicShapes, (cpSpatialIndexIteratorFunc)spaceEachShapeIterator, &context);
+		cpSpatialIndexEach(space->staticShapes, (cpSpatialIndexIteratorFunc)spaceEachShapeIterator, &context);
+	} cpSpaceUnlock(space, cpTrue);
+}
+
+void
+cpSpaceEachConstraint(cpSpace *space, cpSpaceConstraintIteratorFunc func, void *data)
+{
+	cpSpaceLock(space); {
+		cpArray *constraints = space->constraints;
+		
+		for(int i=0; i<constraints->num; i++){
+			func((cpConstraint *)constraints->arr[i], data);
+		}
+	} cpSpaceUnlock(space, cpTrue);
+}
+
+//MARK: Spatial Index Management
+
+void 
+cpSpaceReindexStatic(cpSpace *space)
+{
+	cpAssertHard(!space->locked, "You cannot manually reindex objects while the space is locked. Wait until the current query or step is complete.");
+	
+	cpSpatialIndexEach(space->staticShapes, (cpSpatialIndexIteratorFunc)&cpShapeUpdateFunc, NULL);
+	cpSpatialIndexReindex(space->staticShapes);
+}
+
+void
+cpSpaceReindexShape(cpSpace *space, cpShape *shape)
+{
+	cpAssertHard(!space->locked, "You cannot manually reindex objects while the space is locked. Wait until the current query or step is complete.");
+	
+	cpShapeCacheBB(shape);
+	
+	// attempt to rehash the shape in both hashes
+	cpSpatialIndexReindexObject(space->dynamicShapes, shape, shape->hashid);
+	cpSpatialIndexReindexObject(space->staticShapes, shape, shape->hashid);
+}
+
+void
+cpSpaceReindexShapesForBody(cpSpace *space, cpBody *body)
+{
+	CP_BODY_FOREACH_SHAPE(body, shape) cpSpaceReindexShape(space, shape);
+}
+
+
+static void
+copyShapes(cpShape *shape, cpSpatialIndex *index)
+{
+	cpSpatialIndexInsert(index, shape, shape->hashid);
+}
+
+void
+cpSpaceUseSpatialHash(cpSpace *space, cpFloat dim, int count)
+{
+	cpSpatialIndex *staticShapes = cpSpaceHashNew(dim, count, (cpSpatialIndexBBFunc)cpShapeGetBB, NULL);
+	cpSpatialIndex *dynamicShapes = cpSpaceHashNew(dim, count, (cpSpatialIndexBBFunc)cpShapeGetBB, staticShapes);
+	
+	cpSpatialIndexEach(space->staticShapes, (cpSpatialIndexIteratorFunc)copyShapes, staticShapes);
+	cpSpatialIndexEach(space->dynamicShapes, (cpSpatialIndexIteratorFunc)copyShapes, dynamicShapes);
+	
+	cpSpatialIndexFree(space->staticShapes);
+	cpSpatialIndexFree(space->dynamicShapes);
+	
+	space->staticShapes = staticShapes;
+	space->dynamicShapes = dynamicShapes;
+}
diff --git a/Chipmunk2D-7.0.2/src/cpSpaceComponent.c b/Chipmunk2D-7.0.2/src/cpSpaceComponent.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpSpaceComponent.c
@@ -0,0 +1,349 @@
+/* Copyright (c) 2007 Scott Lembcke
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+ 
+#include <string.h>
+
+#include "chipmunk/chipmunk_private.h"
+
+//MARK: Sleeping Functions
+
+void
+cpSpaceActivateBody(cpSpace *space, cpBody *body)
+{
+	cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "Internal error: Attempting to activate a non-dynamic body.");
+		
+	if(space->locked){
+		// cpSpaceActivateBody() is called again once the space is unlocked
+		if(!cpArrayContains(space->rousedBodies, body)) cpArrayPush(space->rousedBodies, body);
+	} else {
+		cpAssertSoft(body->sleeping.root == NULL && body->sleeping.next == NULL, "Internal error: Activating body non-NULL node pointers.");
+		cpArrayPush(space->dynamicBodies, body);
+
+		CP_BODY_FOREACH_SHAPE(body, shape){
+			cpSpatialIndexRemove(space->staticShapes, shape, shape->hashid);
+			cpSpatialIndexInsert(space->dynamicShapes, shape, shape->hashid);
+		}
+		
+		CP_BODY_FOREACH_ARBITER(body, arb){
+			cpBody *bodyA = arb->body_a;
+			
+			// Arbiters are shared between two bodies that are always woken up together.
+			// You only want to restore the arbiter once, so bodyA is arbitrarily chosen to own the arbiter.
+			// The edge case is when static bodies are involved as the static bodies never actually sleep.
+			// If the static body is bodyB then all is good. If the static body is bodyA, that can easily be checked.
+			if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC){
+				int numContacts = arb->count;
+				struct cpContact *contacts = arb->contacts;
+				
+				// Restore contact values back to the space's contact buffer memory
+				arb->contacts = cpContactBufferGetArray(space);
+				memcpy(arb->contacts, contacts, numContacts*sizeof(struct cpContact));
+				cpSpacePushContacts(space, numContacts);
+				
+				// Reinsert the arbiter into the arbiter cache
+				const cpShape *a = arb->a, *b = arb->b;
+				const cpShape *shape_pair[] = {a, b};
+				cpHashValue arbHashID = CP_HASH_PAIR((cpHashValue)a, (cpHashValue)b);
+				cpHashSetInsert(space->cachedArbiters, arbHashID, shape_pair, NULL, arb);
+				
+				// Update the arbiter's state
+				arb->stamp = space->stamp;
+				cpArrayPush(space->arbiters, arb);
+				
+				cpfree(contacts);
+			}
+		}
+		
+		CP_BODY_FOREACH_CONSTRAINT(body, constraint){
+			cpBody *bodyA = constraint->a;
+			if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC) cpArrayPush(space->constraints, constraint);
+		}
+	}
+}
+
+static void
+cpSpaceDeactivateBody(cpSpace *space, cpBody *body)
+{
+	cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "Internal error: Attempting to deactivate a non-dynamic body.");
+	
+	cpArrayDeleteObj(space->dynamicBodies, body);
+	
+	CP_BODY_FOREACH_SHAPE(body, shape){
+		cpSpatialIndexRemove(space->dynamicShapes, shape, shape->hashid);
+		cpSpatialIndexInsert(space->staticShapes, shape, shape->hashid);
+	}
+	
+	CP_BODY_FOREACH_ARBITER(body, arb){
+		cpBody *bodyA = arb->body_a;
+		if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC){
+			cpSpaceUncacheArbiter(space, arb);
+			
+			// Save contact values to a new block of memory so they won't time out
+			size_t bytes = arb->count*sizeof(struct cpContact);
+			struct cpContact *contacts = (struct cpContact *)cpcalloc(1, bytes);
+			memcpy(contacts, arb->contacts, bytes);
+			arb->contacts = contacts;
+		}
+	}
+		
+	CP_BODY_FOREACH_CONSTRAINT(body, constraint){
+		cpBody *bodyA = constraint->a;
+		if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC) cpArrayDeleteObj(space->constraints, constraint);
+	}
+}
+
+static inline cpBody *
+ComponentRoot(cpBody *body)
+{
+	return (body ? body->sleeping.root : NULL);
+}
+
+void
+cpBodyActivate(cpBody *body)
+{
+	if(body != NULL && cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC){
+		body->sleeping.idleTime = 0.0f;
+		
+		cpBody *root = ComponentRoot(body);
+		if(root && cpBodyIsSleeping(root)){
+			// TODO should cpBodyIsSleeping(root) be an assertion?
+			cpAssertSoft(cpBodyGetType(root) == CP_BODY_TYPE_DYNAMIC, "Internal Error: Non-dynamic body component root detected.");
+			
+			cpSpace *space = root->space;
+			cpBody *body = root;
+			while(body){
+				cpBody *next = body->sleeping.next;
+				
+				body->sleeping.idleTime = 0.0f;
+				body->sleeping.root = NULL;
+				body->sleeping.next = NULL;
+				cpSpaceActivateBody(space, body);
+				
+				body = next;
+			}
+			
+			cpArrayDeleteObj(space->sleepingComponents, root);
+		}
+		
+		CP_BODY_FOREACH_ARBITER(body, arb){
+			// Reset the idle timer of things the body is touching as well.
+			// That way things don't get left hanging in the air.
+			cpBody *other = (arb->body_a == body ? arb->body_b : arb->body_a);
+			if(cpBodyGetType(other) != CP_BODY_TYPE_STATIC) other->sleeping.idleTime = 0.0f;
+		}
+	}
+}
+
+void
+cpBodyActivateStatic(cpBody *body, cpShape *filter)
+{
+	cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_STATIC, "cpBodyActivateStatic() called on a non-static body.");
+	
+	CP_BODY_FOREACH_ARBITER(body, arb){
+		if(!filter || filter == arb->a || filter == arb->b){
+			cpBodyActivate(arb->body_a == body ? arb->body_b : arb->body_a);
+		}
+	}
+	
+	// TODO: should also activate joints?
+}
+
+static inline void
+cpBodyPushArbiter(cpBody *body, cpArbiter *arb)
+{
+	cpAssertSoft(cpArbiterThreadForBody(arb, body)->next == NULL, "Internal Error: Dangling contact graph pointers detected. (A)");
+	cpAssertSoft(cpArbiterThreadForBody(arb, body)->prev == NULL, "Internal Error: Dangling contact graph pointers detected. (B)");
+	
+	cpArbiter *next = body->arbiterList;
+	cpAssertSoft(next == NULL || cpArbiterThreadForBody(next, body)->prev == NULL, "Internal Error: Dangling contact graph pointers detected. (C)");
+	cpArbiterThreadForBody(arb, body)->next = next;
+	
+	if(next) cpArbiterThreadForBody(next, body)->prev = arb;
+	body->arbiterList = arb;
+}
+
+static inline void
+ComponentAdd(cpBody *root, cpBody *body){
+	body->sleeping.root = root;
+
+	if(body != root){
+		body->sleeping.next = root->sleeping.next;
+		root->sleeping.next = body;
+	}
+}
+
+static inline void
+FloodFillComponent(cpBody *root, cpBody *body)
+{
+	// Kinematic bodies cannot be put to sleep and prevent bodies they are touching from sleeping.
+	// Static bodies are effectively sleeping all the time.
+	if(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC){
+		cpBody *other_root = ComponentRoot(body);
+		if(other_root == NULL){
+			ComponentAdd(root, body);
+			CP_BODY_FOREACH_ARBITER(body, arb) FloodFillComponent(root, (body == arb->body_a ? arb->body_b : arb->body_a));
+			CP_BODY_FOREACH_CONSTRAINT(body, constraint) FloodFillComponent(root, (body == constraint->a ? constraint->b : constraint->a));
+		} else {
+			cpAssertSoft(other_root == root, "Internal Error: Inconsistency dectected in the contact graph.");
+		}
+	}
+}
+
+static inline cpBool
+ComponentActive(cpBody *root, cpFloat threshold)
+{
+	CP_BODY_FOREACH_COMPONENT(root, body){
+		if(body->sleeping.idleTime < threshold) return cpTrue;
+	}
+	
+	return cpFalse;
+}
+
+void
+cpSpaceProcessComponents(cpSpace *space, cpFloat dt)
+{
+	cpBool sleep = (space->sleepTimeThreshold != INFINITY);
+	cpArray *bodies = space->dynamicBodies;
+	
+#ifndef NDEBUG
+	for(int i=0; i<bodies->num; i++){
+		cpBody *body = (cpBody*)bodies->arr[i];
+		
+		cpAssertSoft(body->sleeping.next == NULL, "Internal Error: Dangling next pointer detected in contact graph.");
+		cpAssertSoft(body->sleeping.root == NULL, "Internal Error: Dangling root pointer detected in contact graph.");
+	}
+#endif
+	
+	// Calculate the kinetic energy of all the bodies.
+	if(sleep){
+		cpFloat dv = space->idleSpeedThreshold;
+		cpFloat dvsq = (dv ? dv*dv : cpvlengthsq(space->gravity)*dt*dt);
+		
+		// update idling and reset component nodes
+		for(int i=0; i<bodies->num; i++){
+			cpBody *body = (cpBody*)bodies->arr[i];
+			
+			// TODO should make a separate array for kinematic bodies.
+			if(cpBodyGetType(body) != CP_BODY_TYPE_DYNAMIC) continue;
+			
+			// Need to deal with infinite mass objects
+			cpFloat keThreshold = (dvsq ? body->m*dvsq : 0.0f);
+			body->sleeping.idleTime = (cpBodyKineticEnergy(body) > keThreshold ? 0.0f : body->sleeping.idleTime + dt);
+		}
+	}
+	
+	// Awaken any sleeping bodies found and then push arbiters to the bodies' lists.
+	cpArray *arbiters = space->arbiters;
+	for(int i=0, count=arbiters->num; i<count; i++){
+		cpArbiter *arb = (cpArbiter*)arbiters->arr[i];
+		cpBody *a = arb->body_a, *b = arb->body_b;
+		
+		if(sleep){
+			// TODO checking cpBodyIsSleepin() redundant?
+			if(cpBodyGetType(b) == CP_BODY_TYPE_KINEMATIC || cpBodyIsSleeping(a)) cpBodyActivate(a);
+			if(cpBodyGetType(a) == CP_BODY_TYPE_KINEMATIC || cpBodyIsSleeping(b)) cpBodyActivate(b);
+		}
+		
+		cpBodyPushArbiter(a, arb);
+		cpBodyPushArbiter(b, arb);
+	}
+	
+	if(sleep){
+		// Bodies should be held active if connected by a joint to a kinematic.
+		cpArray *constraints = space->constraints;
+		for(int i=0; i<constraints->num; i++){
+			cpConstraint *constraint = (cpConstraint *)constraints->arr[i];
+			cpBody *a = constraint->a, *b = constraint->b;
+			
+			if(cpBodyGetType(b) == CP_BODY_TYPE_KINEMATIC) cpBodyActivate(a);
+			if(cpBodyGetType(a) == CP_BODY_TYPE_KINEMATIC) cpBodyActivate(b);
+		}
+		
+		// Generate components and deactivate sleeping ones
+		for(int i=0; i<bodies->num;){
+			cpBody *body = (cpBody*)bodies->arr[i];
+			
+			if(ComponentRoot(body) == NULL){
+				// Body not in a component yet. Perform a DFS to flood fill mark 
+				// the component in the contact graph using this body as the root.
+				FloodFillComponent(body, body);
+				
+				// Check if the component should be put to sleep.
+				if(!ComponentActive(body, space->sleepTimeThreshold)){
+					cpArrayPush(space->sleepingComponents, body);
+					CP_BODY_FOREACH_COMPONENT(body, other) cpSpaceDeactivateBody(space, other);
+					
+					// cpSpaceDeactivateBody() removed the current body from the list.
+					// Skip incrementing the index counter.
+					continue;
+				}
+			}
+			
+			i++;
+			
+			// Only sleeping bodies retain their component node pointers.
+			body->sleeping.root = NULL;
+			body->sleeping.next = NULL;
+		}
+	}
+}
+
+void
+cpBodySleep(cpBody *body)
+{
+	cpBodySleepWithGroup(body, NULL);
+}
+
+void
+cpBodySleepWithGroup(cpBody *body, cpBody *group){
+	cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "Non-dynamic bodies cannot be put to sleep.");
+	
+	cpSpace *space = body->space;
+	cpAssertHard(!cpSpaceIsLocked(space), "Bodies cannot be put to sleep during a query or a call to cpSpaceStep(). Put these calls into a post-step callback.");
+	cpAssertHard(cpSpaceGetSleepTimeThreshold(space) < INFINITY, "Sleeping is not enabled on the space. You cannot sleep a body without setting a sleep time threshold on the space.");
+	cpAssertHard(group == NULL || cpBodyIsSleeping(group), "Cannot use a non-sleeping body as a group identifier.");
+	
+	if(cpBodyIsSleeping(body)){
+		cpAssertHard(ComponentRoot(body) == ComponentRoot(group), "The body is already sleeping and it's group cannot be reassigned.");
+		return;
+	}
+	
+	CP_BODY_FOREACH_SHAPE(body, shape) cpShapeCacheBB(shape);
+	cpSpaceDeactivateBody(space, body);
+	
+	if(group){
+		cpBody *root = ComponentRoot(group);
+		
+		body->sleeping.root = root;
+		body->sleeping.next = root->sleeping.next;
+		body->sleeping.idleTime = 0.0f;
+		
+		root->sleeping.next = body;
+	} else {
+		body->sleeping.root = body;
+		body->sleeping.next = NULL;
+		body->sleeping.idleTime = 0.0f;
+		
+		cpArrayPush(space->sleepingComponents, body);
+	}
+	
+	cpArrayDeleteObj(space->dynamicBodies, body);
+}
diff --git a/Chipmunk2D-7.0.2/src/cpSpaceDebug.c b/Chipmunk2D-7.0.2/src/cpSpaceDebug.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpSpaceDebug.c
@@ -0,0 +1,189 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+#ifndef CP_SPACE_DISABLE_DEBUG_API
+
+static void
+cpSpaceDebugDrawShape(cpShape *shape, cpSpaceDebugDrawOptions *options)
+{
+	cpBody *body = shape->body;
+	cpDataPointer data = options->data;
+	
+	cpSpaceDebugColor outline_color = options->shapeOutlineColor;
+	cpSpaceDebugColor fill_color = options->colorForShape(shape, data);
+	
+	switch(shape->klass->type){
+		case CP_CIRCLE_SHAPE: {
+			cpCircleShape *circle = (cpCircleShape *)shape;
+			options->drawCircle(circle->tc, body->a, circle->r, outline_color, fill_color, data);
+			break;
+		}
+		case CP_SEGMENT_SHAPE: {
+			cpSegmentShape *seg = (cpSegmentShape *)shape;
+			options->drawFatSegment(seg->ta, seg->tb, seg->r, outline_color, fill_color, data);
+			break;
+		}
+		case CP_POLY_SHAPE: {
+			cpPolyShape *poly = (cpPolyShape *)shape;
+			
+			int count = poly->count;
+			struct cpSplittingPlane *planes = poly->planes;
+			cpVect *verts = (cpVect *)alloca(count*sizeof(cpVect));
+			
+			for(int i=0; i<count; i++) verts[i] = planes[i].v0;
+			options->drawPolygon(count, verts, poly->r, outline_color, fill_color, data);
+			break;
+		}
+		default: break;
+	}
+}
+
+static const cpVect spring_verts[] = {
+	{0.00f, 0.0f},
+	{0.20f, 0.0f},
+	{0.25f, 3.0f},
+	{0.30f,-6.0f},
+	{0.35f, 6.0f},
+	{0.40f,-6.0f},
+	{0.45f, 6.0f},
+	{0.50f,-6.0f},
+	{0.55f, 6.0f},
+	{0.60f,-6.0f},
+	{0.65f, 6.0f},
+	{0.70f,-3.0f},
+	{0.75f, 6.0f},
+	{0.80f, 0.0f},
+	{1.00f, 0.0f},
+};
+static const int spring_count = sizeof(spring_verts)/sizeof(cpVect);
+
+static void
+cpSpaceDebugDrawConstraint(cpConstraint *constraint, cpSpaceDebugDrawOptions *options)
+{
+	cpDataPointer data = options->data;
+	cpSpaceDebugColor color = options->constraintColor;
+	
+	cpBody *body_a = constraint->a;
+	cpBody *body_b = constraint->b;
+
+	if(cpConstraintIsPinJoint(constraint)){
+		cpPinJoint *joint = (cpPinJoint *)constraint;
+		
+		cpVect a = cpTransformPoint(body_a->transform, joint->anchorA);
+		cpVect b = cpTransformPoint(body_b->transform, joint->anchorB);
+		
+		options->drawDot(5, a, color, data);
+		options->drawDot(5, b, color, data);
+		options->drawSegment(a, b, color, data);
+	} else if(cpConstraintIsSlideJoint(constraint)){
+		cpSlideJoint *joint = (cpSlideJoint *)constraint;
+	
+		cpVect a = cpTransformPoint(body_a->transform, joint->anchorA);
+		cpVect b = cpTransformPoint(body_b->transform, joint->anchorB);
+		
+		options->drawDot(5, a, color, data);
+		options->drawDot(5, b, color, data);
+		options->drawSegment(a, b, color, data);
+	} else if(cpConstraintIsPivotJoint(constraint)){
+		cpPivotJoint *joint = (cpPivotJoint *)constraint;
+	
+		cpVect a = cpTransformPoint(body_a->transform, joint->anchorA);
+		cpVect b = cpTransformPoint(body_b->transform, joint->anchorB);
+
+		options->drawDot(5, a, color, data);
+		options->drawDot(5, b, color, data);
+	} else if(cpConstraintIsGrooveJoint(constraint)){
+		cpGrooveJoint *joint = (cpGrooveJoint *)constraint;
+	
+		cpVect a = cpTransformPoint(body_a->transform, joint->grv_a);
+		cpVect b = cpTransformPoint(body_a->transform, joint->grv_b);
+		cpVect c = cpTransformPoint(body_b->transform, joint->anchorB);
+		
+		options->drawDot(5, c, color, data);
+		options->drawSegment(a, b, color, data);
+	} else if(cpConstraintIsDampedSpring(constraint)){
+		cpDampedSpring *spring = (cpDampedSpring *)constraint;
+		cpDataPointer data = options->data;
+		cpSpaceDebugColor color = options->constraintColor;
+		
+		cpVect a = cpTransformPoint(body_a->transform, spring->anchorA);
+		cpVect b = cpTransformPoint(body_b->transform, spring->anchorB);
+		
+		options->drawDot(5, a, color, data);
+		options->drawDot(5, b, color, data);
+
+		cpVect delta = cpvsub(b, a);
+		cpFloat cos = delta.x;
+		cpFloat sin = delta.y;
+		cpFloat s = 1.0f/cpvlength(delta);
+		
+		cpVect r1 = cpv(cos, -sin*s);
+		cpVect r2 = cpv(sin,  cos*s);
+		
+		cpVect *verts = (cpVect *)alloca(spring_count*sizeof(cpVect));
+		for(int i=0; i<spring_count; i++){
+			cpVect v = spring_verts[i];
+			verts[i] = cpv(cpvdot(v, r1) + a.x, cpvdot(v, r2) + a.y);
+		}
+		
+		for(int i=0; i<spring_count-1; i++){
+			options->drawSegment(verts[i], verts[i + 1], color, data);
+		}
+	}
+}
+
+void
+cpSpaceDebugDraw(cpSpace *space, cpSpaceDebugDrawOptions *options)
+{
+	if(options->flags & CP_SPACE_DEBUG_DRAW_SHAPES){
+		cpSpaceEachShape(space, (cpSpaceShapeIteratorFunc)cpSpaceDebugDrawShape, options);
+	}
+	
+	if(options->flags & CP_SPACE_DEBUG_DRAW_CONSTRAINTS){
+		cpSpaceEachConstraint(space, (cpSpaceConstraintIteratorFunc)cpSpaceDebugDrawConstraint, options);
+	}
+	
+	if(options->flags & CP_SPACE_DEBUG_DRAW_COLLISION_POINTS){
+		cpArray *arbiters = space->arbiters;
+		cpSpaceDebugColor color = options->collisionPointColor;
+		cpSpaceDebugDrawSegmentImpl draw_seg = options->drawSegment;
+		cpDataPointer data = options->data;
+		
+		for(int i=0; i<arbiters->num; i++){
+			cpArbiter *arb = (cpArbiter*)arbiters->arr[i];
+			cpVect n = arb->n;
+			
+			for(int j=0; j<arb->count; j++){
+				cpVect p1 = cpvadd(arb->body_a->p, arb->contacts[j].r1);
+				cpVect p2 = cpvadd(arb->body_b->p, arb->contacts[j].r2);
+				
+				cpFloat d = 2.0f;
+				cpVect a = cpvadd(p1, cpvmult(n, -d));
+				cpVect b = cpvadd(p2, cpvmult(n,  d));
+				draw_seg(a, b, color, data);
+			}
+		}
+	}
+}
+
+#endif
diff --git a/Chipmunk2D-7.0.2/src/cpSpaceHash.c b/Chipmunk2D-7.0.2/src/cpSpaceHash.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpSpaceHash.c
@@ -0,0 +1,634 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+#include "prime.h"
+
+typedef struct cpSpaceHashBin cpSpaceHashBin;
+typedef struct cpHandle cpHandle;
+
+struct cpSpaceHash {
+	cpSpatialIndex spatialIndex;
+	
+	int numcells;
+	cpFloat celldim;
+	
+	cpSpaceHashBin **table;
+	cpHashSet *handleSet;
+	
+	cpSpaceHashBin *pooledBins;
+	cpArray *pooledHandles;
+	cpArray *allocatedBuffers;
+	
+	cpTimestamp stamp;
+};
+
+
+//MARK: Handle Functions
+
+struct cpHandle {
+	void *obj;
+	int retain;
+	cpTimestamp stamp;
+};
+
+static cpHandle*
+cpHandleInit(cpHandle *hand, void *obj)
+{
+	hand->obj = obj;
+	hand->retain = 0;
+	hand->stamp = 0;
+	
+	return hand;
+}
+
+static inline void cpHandleRetain(cpHandle *hand){hand->retain++;}
+
+static inline void
+cpHandleRelease(cpHandle *hand, cpArray *pooledHandles)
+{
+	hand->retain--;
+	if(hand->retain == 0) cpArrayPush(pooledHandles, hand);
+}
+
+static int handleSetEql(void *obj, cpHandle *hand){return (obj == hand->obj);}
+
+static void *
+handleSetTrans(void *obj, cpSpaceHash *hash)
+{
+	if(hash->pooledHandles->num == 0){
+		// handle pool is exhausted, make more
+		int count = CP_BUFFER_BYTES/sizeof(cpHandle);
+		cpAssertHard(count, "Internal Error: Buffer size is too small.");
+		
+		cpHandle *buffer = (cpHandle *)cpcalloc(1, CP_BUFFER_BYTES);
+		cpArrayPush(hash->allocatedBuffers, buffer);
+		
+		for(int i=0; i<count; i++) cpArrayPush(hash->pooledHandles, buffer + i);
+	}
+	
+	cpHandle *hand = cpHandleInit((cpHandle *)cpArrayPop(hash->pooledHandles), obj);
+	cpHandleRetain(hand);
+	
+	return hand;
+}
+
+//MARK: Bin Functions
+
+struct cpSpaceHashBin {
+	cpHandle *handle;
+	cpSpaceHashBin *next;
+};
+
+static inline void
+recycleBin(cpSpaceHash *hash, cpSpaceHashBin *bin)
+{
+	bin->next = hash->pooledBins;
+	hash->pooledBins = bin;
+}
+
+static inline void
+clearTableCell(cpSpaceHash *hash, int idx)
+{
+	cpSpaceHashBin *bin = hash->table[idx];
+	while(bin){
+		cpSpaceHashBin *next = bin->next;
+		
+		cpHandleRelease(bin->handle, hash->pooledHandles);
+		recycleBin(hash, bin);
+		
+		bin = next;
+	}
+	
+	hash->table[idx] = NULL;
+}
+
+static void
+clearTable(cpSpaceHash *hash)
+{
+	for(int i=0; i<hash->numcells; i++) clearTableCell(hash, i);
+}
+
+// Get a recycled or new bin.
+static inline cpSpaceHashBin *
+getEmptyBin(cpSpaceHash *hash)
+{
+	cpSpaceHashBin *bin = hash->pooledBins;
+	
+	if(bin){
+		hash->pooledBins = bin->next;
+		return bin;
+	} else {
+		// Pool is exhausted, make more
+		int count = CP_BUFFER_BYTES/sizeof(cpSpaceHashBin);
+		cpAssertHard(count, "Internal Error: Buffer size is too small.");
+		
+		cpSpaceHashBin *buffer = (cpSpaceHashBin *)cpcalloc(1, CP_BUFFER_BYTES);
+		cpArrayPush(hash->allocatedBuffers, buffer);
+		
+		// push all but the first one, return the first instead
+		for(int i=1; i<count; i++) recycleBin(hash, buffer + i);
+		return buffer;
+	}
+}
+
+//MARK: Memory Management Functions
+
+cpSpaceHash *
+cpSpaceHashAlloc(void)
+{
+	return (cpSpaceHash *)cpcalloc(1, sizeof(cpSpaceHash));
+}
+
+// Frees the old table, and allocate a new one.
+static void
+cpSpaceHashAllocTable(cpSpaceHash *hash, int numcells)
+{
+	cpfree(hash->table);
+	
+	hash->numcells = numcells;
+	hash->table = (cpSpaceHashBin **)cpcalloc(numcells, sizeof(cpSpaceHashBin *));
+}
+
+static inline cpSpatialIndexClass *Klass();
+
+cpSpatialIndex *
+cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int numcells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
+{
+	cpSpatialIndexInit((cpSpatialIndex *)hash, Klass(), bbfunc, staticIndex);
+	
+	cpSpaceHashAllocTable(hash, next_prime(numcells));
+	hash->celldim = celldim;
+	
+	hash->handleSet = cpHashSetNew(0, (cpHashSetEqlFunc)handleSetEql);
+	
+	hash->pooledHandles = cpArrayNew(0);
+	
+	hash->pooledBins = NULL;
+	hash->allocatedBuffers = cpArrayNew(0);
+	
+	hash->stamp = 1;
+	
+	return (cpSpatialIndex *)hash;
+}
+
+cpSpatialIndex *
+cpSpaceHashNew(cpFloat celldim, int cells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
+{
+	return cpSpaceHashInit(cpSpaceHashAlloc(), celldim, cells, bbfunc, staticIndex);
+}
+
+static void
+cpSpaceHashDestroy(cpSpaceHash *hash)
+{
+	if(hash->table) clearTable(hash);
+	cpfree(hash->table);
+	
+	cpHashSetFree(hash->handleSet);
+	
+	cpArrayFreeEach(hash->allocatedBuffers, cpfree);
+	cpArrayFree(hash->allocatedBuffers);
+	cpArrayFree(hash->pooledHandles);
+}
+
+//MARK: Helper Functions
+
+static inline cpBool
+containsHandle(cpSpaceHashBin *bin, cpHandle *hand)
+{
+	while(bin){
+		if(bin->handle == hand) return cpTrue;
+		bin = bin->next;
+	}
+	
+	return cpFalse;
+}
+
+// The hash function itself.
+static inline cpHashValue
+hash_func(cpHashValue x, cpHashValue y, cpHashValue n)
+{
+	return (x*1640531513ul ^ y*2654435789ul) % n;
+}
+
+// Much faster than (int)floor(f)
+// Profiling showed floor() to be a sizable performance hog
+static inline int
+floor_int(cpFloat f)
+{
+	int i = (int)f;
+	return (f < 0.0f && f != i ? i - 1 : i);
+}
+
+static inline void
+hashHandle(cpSpaceHash *hash, cpHandle *hand, cpBB bb)
+{
+	// Find the dimensions in cell coordinates.
+	cpFloat dim = hash->celldim;
+	int l = floor_int(bb.l/dim); // Fix by ShiftZ
+	int r = floor_int(bb.r/dim);
+	int b = floor_int(bb.b/dim);
+	int t = floor_int(bb.t/dim);
+	
+	int n = hash->numcells;
+	for(int i=l; i<=r; i++){
+		for(int j=b; j<=t; j++){
+			cpHashValue idx = hash_func(i,j,n);
+			cpSpaceHashBin *bin = hash->table[idx];
+			
+			// Don't add an object twice to the same cell.
+			if(containsHandle(bin, hand)) continue;
+
+			cpHandleRetain(hand);
+			// Insert a new bin for the handle in this cell.
+			cpSpaceHashBin *newBin = getEmptyBin(hash);
+			newBin->handle = hand;
+			newBin->next = bin;
+			hash->table[idx] = newBin;
+		}
+	}
+}
+
+//MARK: Basic Operations
+
+static void
+cpSpaceHashInsert(cpSpaceHash *hash, void *obj, cpHashValue hashid)
+{
+	cpHandle *hand = (cpHandle *)cpHashSetInsert(hash->handleSet, hashid, obj, (cpHashSetTransFunc)handleSetTrans, hash);
+	hashHandle(hash, hand, hash->spatialIndex.bbfunc(obj));
+}
+
+static void
+cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj, cpHashValue hashid)
+{
+	cpHandle *hand = (cpHandle *)cpHashSetRemove(hash->handleSet, hashid, obj);
+	
+	if(hand){
+		hand->obj = NULL;
+		cpHandleRelease(hand, hash->pooledHandles);
+		
+		cpSpaceHashInsert(hash, obj, hashid);
+	}
+}
+
+static void
+rehash_helper(cpHandle *hand, cpSpaceHash *hash)
+{
+	hashHandle(hash, hand, hash->spatialIndex.bbfunc(hand->obj));
+}
+
+static void
+cpSpaceHashRehash(cpSpaceHash *hash)
+{
+	clearTable(hash);
+	cpHashSetEach(hash->handleSet, (cpHashSetIteratorFunc)rehash_helper, hash);
+}
+
+static void
+cpSpaceHashRemove(cpSpaceHash *hash, void *obj, cpHashValue hashid)
+{
+	cpHandle *hand = (cpHandle *)cpHashSetRemove(hash->handleSet, hashid, obj);
+	
+	if(hand){
+		hand->obj = NULL;
+		cpHandleRelease(hand, hash->pooledHandles);
+	}
+}
+
+typedef struct eachContext {
+	cpSpatialIndexIteratorFunc func;
+	void *data;
+} eachContext;
+
+static void eachHelper(cpHandle *hand, eachContext *context){context->func(hand->obj, context->data);}
+
+static void
+cpSpaceHashEach(cpSpaceHash *hash, cpSpatialIndexIteratorFunc func, void *data)
+{
+	eachContext context = {func, data};
+	cpHashSetEach(hash->handleSet, (cpHashSetIteratorFunc)eachHelper, &context);
+}
+
+static void
+remove_orphaned_handles(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr)
+{
+	cpSpaceHashBin *bin = *bin_ptr;
+	while(bin){
+		cpHandle *hand = bin->handle;
+		cpSpaceHashBin *next = bin->next;
+		
+		if(!hand->obj){
+			// orphaned handle, unlink and recycle the bin
+			(*bin_ptr) = bin->next;
+			recycleBin(hash, bin);
+			
+			cpHandleRelease(hand, hash->pooledHandles);
+		} else {
+			bin_ptr = &bin->next;
+		}
+		
+		bin = next;
+	}
+}
+
+//MARK: Query Functions
+
+static inline void
+query_helper(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr, void *obj, cpSpatialIndexQueryFunc func, void *data)
+{
+	restart:
+	for(cpSpaceHashBin *bin = *bin_ptr; bin; bin = bin->next){
+		cpHandle *hand = bin->handle;
+		void *other = hand->obj;
+		
+		if(hand->stamp == hash->stamp || obj == other){
+			continue;
+		} else if(other){
+			func(obj, other, 0, data);
+			hand->stamp = hash->stamp;
+		} else {
+			// The object for this handle has been removed
+			// cleanup this cell and restart the query
+			remove_orphaned_handles(hash, bin_ptr);
+			goto restart; // GCC not smart enough/able to tail call an inlined function.
+		}
+	}
+}
+
+static void
+cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data)
+{
+	// Get the dimensions in cell coordinates.
+	cpFloat dim = hash->celldim;
+	int l = floor_int(bb.l/dim);  // Fix by ShiftZ
+	int r = floor_int(bb.r/dim);
+	int b = floor_int(bb.b/dim);
+	int t = floor_int(bb.t/dim);
+	
+	int n = hash->numcells;
+	cpSpaceHashBin **table = hash->table;
+	
+	// Iterate over the cells and query them.
+	for(int i=l; i<=r; i++){
+		for(int j=b; j<=t; j++){
+			query_helper(hash, &table[hash_func(i,j,n)], obj, func, data);
+		}
+	}
+	
+	hash->stamp++;
+}
+
+// Similar to struct eachPair above.
+typedef struct queryRehashContext {
+	cpSpaceHash *hash;
+	cpSpatialIndexQueryFunc func;
+	void *data;
+} queryRehashContext;
+
+// Hashset iterator func used with cpSpaceHashQueryRehash().
+static void
+queryRehash_helper(cpHandle *hand, queryRehashContext *context)
+{
+	cpSpaceHash *hash = context->hash;
+	cpSpatialIndexQueryFunc func = context->func;
+	void *data = context->data;
+
+	cpFloat dim = hash->celldim;
+	int n = hash->numcells;
+
+	void *obj = hand->obj;
+	cpBB bb = hash->spatialIndex.bbfunc(obj);
+
+	int l = floor_int(bb.l/dim);
+	int r = floor_int(bb.r/dim);
+	int b = floor_int(bb.b/dim);
+	int t = floor_int(bb.t/dim);
+	
+	cpSpaceHashBin **table = hash->table;
+
+	for(int i=l; i<=r; i++){
+		for(int j=b; j<=t; j++){
+			cpHashValue idx = hash_func(i,j,n);
+			cpSpaceHashBin *bin = table[idx];
+			
+			if(containsHandle(bin, hand)) continue;
+			
+			cpHandleRetain(hand); // this MUST be done first in case the object is removed in func()
+			query_helper(hash, &bin, obj, func, data);
+			
+			cpSpaceHashBin *newBin = getEmptyBin(hash);
+			newBin->handle = hand;
+			newBin->next = bin;
+			table[idx] = newBin;
+		}
+	}
+	
+	// Increment the stamp for each object hashed.
+	hash->stamp++;
+}
+
+static void
+cpSpaceHashReindexQuery(cpSpaceHash *hash, cpSpatialIndexQueryFunc func, void *data)
+{
+	clearTable(hash);
+	
+	queryRehashContext context = {hash, func, data};
+	cpHashSetEach(hash->handleSet, (cpHashSetIteratorFunc)queryRehash_helper, &context);
+	
+	cpSpatialIndexCollideStatic((cpSpatialIndex *)hash, hash->spatialIndex.staticIndex, func, data);
+}
+
+static inline cpFloat
+segmentQuery_helper(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr, void *obj, cpSpatialIndexSegmentQueryFunc func, void *data)
+{
+	cpFloat t = 1.0f;
+	 
+	restart:
+	for(cpSpaceHashBin *bin = *bin_ptr; bin; bin = bin->next){
+		cpHandle *hand = bin->handle;
+		void *other = hand->obj;
+		
+		// Skip over certain conditions
+		if(hand->stamp == hash->stamp){
+			continue;
+		} else if(other){
+			t = cpfmin(t, func(obj, other, data));
+			hand->stamp = hash->stamp;
+		} else {
+			// The object for this handle has been removed
+			// cleanup this cell and restart the query
+			remove_orphaned_handles(hash, bin_ptr);
+			goto restart; // GCC not smart enough/able to tail call an inlined function.
+		}
+	}
+	
+	return t;
+}
+
+// modified from http://playtechs.blogspot.com/2007/03/raytracing-on-grid.html
+static void
+cpSpaceHashSegmentQuery(cpSpaceHash *hash, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data)
+{
+	a = cpvmult(a, 1.0f/hash->celldim);
+	b = cpvmult(b, 1.0f/hash->celldim);
+	
+	int cell_x = floor_int(a.x), cell_y = floor_int(a.y);
+
+	cpFloat t = 0;
+
+	int x_inc, y_inc;
+	cpFloat temp_v, temp_h;
+
+	if (b.x > a.x){
+		x_inc = 1;
+		temp_h = (cpffloor(a.x + 1.0f) - a.x);
+	} else {
+		x_inc = -1;
+		temp_h = (a.x - cpffloor(a.x));
+	}
+
+	if (b.y > a.y){
+		y_inc = 1;
+		temp_v = (cpffloor(a.y + 1.0f) - a.y);
+	} else {
+		y_inc = -1;
+		temp_v = (a.y - cpffloor(a.y));
+	}
+	
+	// Division by zero is *very* slow on ARM
+	cpFloat dx = cpfabs(b.x - a.x), dy = cpfabs(b.y - a.y);
+	cpFloat dt_dx = (dx ? 1.0f/dx : INFINITY), dt_dy = (dy ? 1.0f/dy : INFINITY);
+	
+	// fix NANs in horizontal directions
+	cpFloat next_h = (temp_h ? temp_h*dt_dx : dt_dx);
+	cpFloat next_v = (temp_v ? temp_v*dt_dy : dt_dy);
+	
+	int n = hash->numcells;
+	cpSpaceHashBin **table = hash->table;
+
+	while(t < t_exit){
+		cpHashValue idx = hash_func(cell_x, cell_y, n);
+		t_exit = cpfmin(t_exit, segmentQuery_helper(hash, &table[idx], obj, func, data));
+
+		if (next_v < next_h){
+			cell_y += y_inc;
+			t = next_v;
+			next_v += dt_dy;
+		} else {
+			cell_x += x_inc;
+			t = next_h;
+			next_h += dt_dx;
+		}
+	}
+	
+	hash->stamp++;
+}
+
+//MARK: Misc
+
+void
+cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells)
+{
+	if(hash->spatialIndex.klass != Klass()){
+		cpAssertWarn(cpFalse, "Ignoring cpSpaceHashResize() call to non-cpSpaceHash spatial index.");
+		return;
+	}
+	
+	clearTable(hash);
+	
+	hash->celldim = celldim;
+	cpSpaceHashAllocTable(hash, next_prime(numcells));
+}
+
+static int
+cpSpaceHashCount(cpSpaceHash *hash)
+{
+	return cpHashSetCount(hash->handleSet);
+}
+
+static int
+cpSpaceHashContains(cpSpaceHash *hash, void *obj, cpHashValue hashid)
+{
+	return cpHashSetFind(hash->handleSet, hashid, obj) != NULL;
+}
+
+static cpSpatialIndexClass klass = {
+	(cpSpatialIndexDestroyImpl)cpSpaceHashDestroy,
+	
+	(cpSpatialIndexCountImpl)cpSpaceHashCount,
+	(cpSpatialIndexEachImpl)cpSpaceHashEach,
+	(cpSpatialIndexContainsImpl)cpSpaceHashContains,
+	
+	(cpSpatialIndexInsertImpl)cpSpaceHashInsert,
+	(cpSpatialIndexRemoveImpl)cpSpaceHashRemove,
+	
+	(cpSpatialIndexReindexImpl)cpSpaceHashRehash,
+	(cpSpatialIndexReindexObjectImpl)cpSpaceHashRehashObject,
+	(cpSpatialIndexReindexQueryImpl)cpSpaceHashReindexQuery,
+	
+	(cpSpatialIndexQueryImpl)cpSpaceHashQuery,
+	(cpSpatialIndexSegmentQueryImpl)cpSpaceHashSegmentQuery,
+};
+
+static inline cpSpatialIndexClass *Klass(){return &klass;}
+
+//MARK: Debug Drawing
+
+//#define CP_BBTREE_DEBUG_DRAW
+#ifdef CP_BBTREE_DEBUG_DRAW
+#include "OpenGL/gl.h"
+#include "OpenGL/glu.h"
+#include <GLUT/glut.h>
+
+void
+cpSpaceHashRenderDebug(cpSpatialIndex *index)
+{
+	if(index->klass != &klass){
+		cpAssertWarn(cpFalse, "Ignoring cpSpaceHashRenderDebug() call to non-spatial hash spatial index.");
+		return;
+	}
+	
+	cpSpaceHash *hash = (cpSpaceHash *)index;
+	cpBB bb = cpBBNew(-320, -240, 320, 240);
+	
+	cpFloat dim = hash->celldim;
+	int n = hash->numcells;
+	
+	int l = (int)floor(bb.l/dim);
+	int r = (int)floor(bb.r/dim);
+	int b = (int)floor(bb.b/dim);
+	int t = (int)floor(bb.t/dim);
+	
+	for(int i=l; i<=r; i++){
+		for(int j=b; j<=t; j++){
+			int cell_count = 0;
+			
+			int index = hash_func(i,j,n);
+			for(cpSpaceHashBin *bin = hash->table[index]; bin; bin = bin->next)
+				cell_count++;
+			
+			GLfloat v = 1.0f - (GLfloat)cell_count/10.0f;
+			glColor3f(v,v,v);
+			glRectf(i*dim, j*dim, (i + 1)*dim, (j + 1)*dim);
+		}
+	}
+}
+#endif
diff --git a/Chipmunk2D-7.0.2/src/cpSpaceQuery.c b/Chipmunk2D-7.0.2/src/cpSpaceQuery.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpSpaceQuery.c
@@ -0,0 +1,246 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+//MARK: Nearest Point Query Functions
+
+struct PointQueryContext {
+	cpVect point;
+	cpFloat maxDistance;
+	cpShapeFilter filter;
+	cpSpacePointQueryFunc func;
+};
+
+static cpCollisionID
+NearestPointQuery(struct PointQueryContext *context, cpShape *shape, cpCollisionID id, void *data)
+{
+	if(
+		!cpShapeFilterReject(shape->filter, context->filter)
+	){
+		cpPointQueryInfo info;
+		cpShapePointQuery(shape, context->point, &info);
+		
+		if(info.shape && info.distance < context->maxDistance) context->func(shape, info.point, info.distance, info.gradient, data);
+	}
+	
+	return id;
+}
+
+void
+cpSpacePointQuery(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpSpacePointQueryFunc func, void *data)
+{
+	struct PointQueryContext context = {point, maxDistance, filter, func};
+	cpBB bb = cpBBNewForCircle(point, cpfmax(maxDistance, 0.0f));
+	
+	cpSpaceLock(space); {
+		cpSpatialIndexQuery(space->dynamicShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQuery, data);
+		cpSpatialIndexQuery(space->staticShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQuery, data);
+	} cpSpaceUnlock(space, cpTrue);
+}
+
+static cpCollisionID
+NearestPointQueryNearest(struct PointQueryContext *context, cpShape *shape, cpCollisionID id, cpPointQueryInfo *out)
+{
+	if(
+		!cpShapeFilterReject(shape->filter, context->filter) && !shape->sensor
+	){
+		cpPointQueryInfo info;
+		cpShapePointQuery(shape, context->point, &info);
+		
+		if(info.distance < out->distance) (*out) = info;
+	}
+	
+	return id;
+}
+
+cpShape *
+cpSpacePointQueryNearest(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpPointQueryInfo *out)
+{
+	cpPointQueryInfo info = {NULL, cpvzero, maxDistance, cpvzero};
+	if(out){
+		(*out) = info;
+  } else {
+		out = &info;
+	}
+	
+	struct PointQueryContext context = {
+		point, maxDistance,
+		filter,
+		NULL
+	};
+	
+	cpBB bb = cpBBNewForCircle(point, cpfmax(maxDistance, 0.0f));
+	cpSpatialIndexQuery(space->dynamicShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQueryNearest, out);
+	cpSpatialIndexQuery(space->staticShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQueryNearest, out);
+	
+	return (cpShape *)out->shape;
+}
+
+
+//MARK: Segment Query Functions
+
+struct SegmentQueryContext {
+	cpVect start, end;
+	cpFloat radius;
+	cpShapeFilter filter;
+	cpSpaceSegmentQueryFunc func;
+};
+
+static cpFloat
+SegmentQuery(struct SegmentQueryContext *context, cpShape *shape, void *data)
+{
+	cpSegmentQueryInfo info;
+	
+	if(
+		!cpShapeFilterReject(shape->filter, context->filter) &&
+		cpShapeSegmentQuery(shape, context->start, context->end, context->radius, &info)
+	){
+		context->func(shape, info.point, info.normal, info.alpha, data);
+	}
+	
+	return 1.0f;
+}
+
+void
+cpSpaceSegmentQuery(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSpaceSegmentQueryFunc func, void *data)
+{
+	struct SegmentQueryContext context = {
+		start, end,
+		radius,
+		filter,
+		func,
+	};
+	
+	cpSpaceLock(space); {
+    cpSpatialIndexSegmentQuery(space->staticShapes, &context, start, end, 1.0f, (cpSpatialIndexSegmentQueryFunc)SegmentQuery, data);
+    cpSpatialIndexSegmentQuery(space->dynamicShapes, &context, start, end, 1.0f, (cpSpatialIndexSegmentQueryFunc)SegmentQuery, data);
+	} cpSpaceUnlock(space, cpTrue);
+}
+
+static cpFloat
+SegmentQueryFirst(struct SegmentQueryContext *context, cpShape *shape, cpSegmentQueryInfo *out)
+{
+	cpSegmentQueryInfo info;
+	
+	if(
+		!cpShapeFilterReject(shape->filter, context->filter) && !shape->sensor &&
+		cpShapeSegmentQuery(shape, context->start, context->end, context->radius, &info) &&
+		info.alpha < out->alpha
+	){
+		(*out) = info;
+	}
+	
+	return out->alpha;
+}
+
+cpShape *
+cpSpaceSegmentQueryFirst(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSegmentQueryInfo *out)
+{
+	cpSegmentQueryInfo info = {NULL, end, cpvzero, 1.0f};
+	if(out){
+		(*out) = info;
+  } else {
+		out = &info;
+	}
+	
+	struct SegmentQueryContext context = {
+		start, end,
+		radius,
+		filter,
+		NULL
+	};
+	
+	cpSpatialIndexSegmentQuery(space->staticShapes, &context, start, end, 1.0f, (cpSpatialIndexSegmentQueryFunc)SegmentQueryFirst, out);
+	cpSpatialIndexSegmentQuery(space->dynamicShapes, &context, start, end, out->alpha, (cpSpatialIndexSegmentQueryFunc)SegmentQueryFirst, out);
+	
+	return (cpShape *)out->shape;
+}
+
+//MARK: BB Query Functions
+
+struct BBQueryContext {
+	cpBB bb;
+	cpShapeFilter filter;
+	cpSpaceBBQueryFunc func;
+};
+
+static cpCollisionID
+BBQuery(struct BBQueryContext *context, cpShape *shape, cpCollisionID id, void *data)
+{
+	if(
+		!cpShapeFilterReject(shape->filter, context->filter) &&
+		cpBBIntersects(context->bb, shape->bb)
+	){
+		context->func(shape, data);
+	}
+	
+	return id;
+}
+
+void
+cpSpaceBBQuery(cpSpace *space, cpBB bb, cpShapeFilter filter, cpSpaceBBQueryFunc func, void *data)
+{
+	struct BBQueryContext context = {bb, filter, func};
+	
+	cpSpaceLock(space); {
+    cpSpatialIndexQuery(space->dynamicShapes, &context, bb, (cpSpatialIndexQueryFunc)BBQuery, data);
+    cpSpatialIndexQuery(space->staticShapes, &context, bb, (cpSpatialIndexQueryFunc)BBQuery, data);
+	} cpSpaceUnlock(space, cpTrue);
+}
+
+//MARK: Shape Query Functions
+
+struct ShapeQueryContext {
+	cpSpaceShapeQueryFunc func;
+	void *data;
+	cpBool anyCollision;
+};
+
+// Callback from the spatial hash.
+static cpCollisionID
+ShapeQuery(cpShape *a, cpShape *b, cpCollisionID id, struct ShapeQueryContext *context)
+{
+	if(cpShapeFilterReject(a->filter, b->filter) || a == b) return id;
+	
+	cpContactPointSet set = cpShapesCollide(a, b);
+	if(set.count){
+		if(context->func) context->func(b, &set, context->data);
+		context->anyCollision = !(a->sensor || b->sensor);
+	}
+	
+	return id;
+}
+
+cpBool
+cpSpaceShapeQuery(cpSpace *space, cpShape *shape, cpSpaceShapeQueryFunc func, void *data)
+{
+	cpBody *body = shape->body;
+	cpBB bb = (body ? cpShapeUpdate(shape, body->transform) : shape->bb);
+	struct ShapeQueryContext context = {func, data, cpFalse};
+	
+	cpSpaceLock(space); {
+    cpSpatialIndexQuery(space->dynamicShapes, shape, bb, (cpSpatialIndexQueryFunc)ShapeQuery, &context);
+    cpSpatialIndexQuery(space->staticShapes, shape, bb, (cpSpatialIndexQueryFunc)ShapeQuery, &context);
+	} cpSpaceUnlock(space, cpTrue);
+	
+	return context.anyCollision;
+}
diff --git a/Chipmunk2D-7.0.2/src/cpSpaceStep.c b/Chipmunk2D-7.0.2/src/cpSpaceStep.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpSpaceStep.c
@@ -0,0 +1,445 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+//MARK: Post Step Callback Functions
+
+cpPostStepCallback *
+cpSpaceGetPostStepCallback(cpSpace *space, void *key)
+{
+	cpArray *arr = space->postStepCallbacks;
+	for(int i=0; i<arr->num; i++){
+		cpPostStepCallback *callback = (cpPostStepCallback *)arr->arr[i];
+		if(callback && callback->key == key) return callback;
+	}
+	
+	return NULL;
+}
+
+static void PostStepDoNothing(cpSpace *space, void *obj, void *data){}
+
+cpBool
+cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *key, void *data)
+{
+	cpAssertWarn(space->locked,
+		"Adding a post-step callback when the space is not locked is unnecessary. "
+		"Post-step callbacks will not called until the end of the next call to cpSpaceStep() or the next query.");
+	
+	if(!cpSpaceGetPostStepCallback(space, key)){
+		cpPostStepCallback *callback = (cpPostStepCallback *)cpcalloc(1, sizeof(cpPostStepCallback));
+		callback->func = (func ? func : PostStepDoNothing);
+		callback->key = key;
+		callback->data = data;
+		
+		cpArrayPush(space->postStepCallbacks, callback);
+		return cpTrue;
+	} else {
+		return cpFalse;
+	}
+}
+
+//MARK: Locking Functions
+
+void
+cpSpaceLock(cpSpace *space)
+{
+	space->locked++;
+}
+
+void
+cpSpaceUnlock(cpSpace *space, cpBool runPostStep)
+{
+	space->locked--;
+	cpAssertHard(space->locked >= 0, "Internal Error: Space lock underflow.");
+	
+	if(space->locked == 0){
+		cpArray *waking = space->rousedBodies;
+		
+		for(int i=0, count=waking->num; i<count; i++){
+			cpSpaceActivateBody(space, (cpBody *)waking->arr[i]);
+			waking->arr[i] = NULL;
+		}
+		
+		waking->num = 0;
+		
+		if(space->locked == 0 && runPostStep && !space->skipPostStep){
+			space->skipPostStep = cpTrue;
+			
+			cpArray *arr = space->postStepCallbacks;
+			for(int i=0; i<arr->num; i++){
+				cpPostStepCallback *callback = (cpPostStepCallback *)arr->arr[i];
+				cpPostStepFunc func = callback->func;
+				
+				// Mark the func as NULL in case calling it calls cpSpaceRunPostStepCallbacks() again.
+				// TODO: need more tests around this case I think.
+				callback->func = NULL;
+				if(func) func(space, callback->key, callback->data);
+				
+				arr->arr[i] = NULL;
+				cpfree(callback);
+			}
+			
+			arr->num = 0;
+			space->skipPostStep = cpFalse;
+		}
+	}
+}
+
+//MARK: Contact Buffer Functions
+
+struct cpContactBufferHeader {
+	cpTimestamp stamp;
+	cpContactBufferHeader *next;
+	unsigned int numContacts;
+};
+
+#define CP_CONTACTS_BUFFER_SIZE ((CP_BUFFER_BYTES - sizeof(cpContactBufferHeader))/sizeof(struct cpContact))
+typedef struct cpContactBuffer {
+	cpContactBufferHeader header;
+	struct cpContact contacts[CP_CONTACTS_BUFFER_SIZE];
+} cpContactBuffer;
+
+static cpContactBufferHeader *
+cpSpaceAllocContactBuffer(cpSpace *space)
+{
+	cpContactBuffer *buffer = (cpContactBuffer *)cpcalloc(1, sizeof(cpContactBuffer));
+	cpArrayPush(space->allocatedBuffers, buffer);
+	return (cpContactBufferHeader *)buffer;
+}
+
+static cpContactBufferHeader *
+cpContactBufferHeaderInit(cpContactBufferHeader *header, cpTimestamp stamp, cpContactBufferHeader *splice)
+{
+	header->stamp = stamp;
+	header->next = (splice ? splice->next : header);
+	header->numContacts = 0;
+	
+	return header;
+}
+
+void
+cpSpacePushFreshContactBuffer(cpSpace *space)
+{
+	cpTimestamp stamp = space->stamp;
+	
+	cpContactBufferHeader *head = space->contactBuffersHead;
+	
+	if(!head){
+		// No buffers have been allocated, make one
+		space->contactBuffersHead = cpContactBufferHeaderInit(cpSpaceAllocContactBuffer(space), stamp, NULL);
+	} else if(stamp - head->next->stamp > space->collisionPersistence){
+		// The tail buffer is available, rotate the ring
+	cpContactBufferHeader *tail = head->next;
+		space->contactBuffersHead = cpContactBufferHeaderInit(tail, stamp, tail);
+	} else {
+		// Allocate a new buffer and push it into the ring
+		cpContactBufferHeader *buffer = cpContactBufferHeaderInit(cpSpaceAllocContactBuffer(space), stamp, head);
+		space->contactBuffersHead = head->next = buffer;
+	}
+}
+
+
+struct cpContact *
+cpContactBufferGetArray(cpSpace *space)
+{
+	if(space->contactBuffersHead->numContacts + CP_MAX_CONTACTS_PER_ARBITER > CP_CONTACTS_BUFFER_SIZE){
+		// contact buffer could overflow on the next collision, push a fresh one.
+		cpSpacePushFreshContactBuffer(space);
+	}
+	
+	cpContactBufferHeader *head = space->contactBuffersHead;
+	return ((cpContactBuffer *)head)->contacts + head->numContacts;
+}
+
+void
+cpSpacePushContacts(cpSpace *space, int count)
+{
+	cpAssertHard(count <= CP_MAX_CONTACTS_PER_ARBITER, "Internal Error: Contact buffer overflow!");
+	space->contactBuffersHead->numContacts += count;
+}
+
+static void
+cpSpacePopContacts(cpSpace *space, int count){
+	space->contactBuffersHead->numContacts -= count;
+}
+
+//MARK: Collision Detection Functions
+
+static void *
+cpSpaceArbiterSetTrans(cpShape **shapes, cpSpace *space)
+{
+	if(space->pooledArbiters->num == 0){
+		// arbiter pool is exhausted, make more
+		int count = CP_BUFFER_BYTES/sizeof(cpArbiter);
+		cpAssertHard(count, "Internal Error: Buffer size too small.");
+		
+		cpArbiter *buffer = (cpArbiter *)cpcalloc(1, CP_BUFFER_BYTES);
+		cpArrayPush(space->allocatedBuffers, buffer);
+		
+		for(int i=0; i<count; i++) cpArrayPush(space->pooledArbiters, buffer + i);
+	}
+	
+	return cpArbiterInit((cpArbiter *)cpArrayPop(space->pooledArbiters), shapes[0], shapes[1]);
+}
+
+static inline cpBool
+QueryRejectConstraint(cpBody *a, cpBody *b)
+{
+	CP_BODY_FOREACH_CONSTRAINT(a, constraint){
+		if(
+			!constraint->collideBodies && (
+				(constraint->a == a && constraint->b == b) ||
+				(constraint->a == b && constraint->b == a)
+			)
+		) return cpTrue;
+	}
+	
+	return cpFalse;
+}
+
+static inline cpBool
+QueryReject(cpShape *a, cpShape *b)
+{
+	return (
+		// BBoxes must overlap
+		!cpBBIntersects(a->bb, b->bb)
+		// Don't collide shapes attached to the same body.
+		|| a->body == b->body
+		// Don't collide shapes that are filtered.
+		|| cpShapeFilterReject(a->filter, b->filter)
+		// Don't collide bodies if they have a constraint with collideBodies == cpFalse.
+		|| QueryRejectConstraint(a->body, b->body)
+	);
+}
+
+// Callback from the spatial hash.
+cpCollisionID
+cpSpaceCollideShapes(cpShape *a, cpShape *b, cpCollisionID id, cpSpace *space)
+{
+	// Reject any of the simple cases
+	if(QueryReject(a,b)) return id;
+	
+	// Narrow-phase collision detection.
+	struct cpCollisionInfo info = cpCollide(a, b, id, cpContactBufferGetArray(space));
+	
+	if(info.count == 0) return info.id; // Shapes are not colliding.
+	cpSpacePushContacts(space, info.count);
+	
+	// Get an arbiter from space->arbiterSet for the two shapes.
+	// This is where the persistant contact magic comes from.
+	const cpShape *shape_pair[] = {info.a, info.b};
+	cpHashValue arbHashID = CP_HASH_PAIR((cpHashValue)info.a, (cpHashValue)info.b);
+	cpArbiter *arb = (cpArbiter *)cpHashSetInsert(space->cachedArbiters, arbHashID, shape_pair, (cpHashSetTransFunc)cpSpaceArbiterSetTrans, space);
+	cpArbiterUpdate(arb, &info, space);
+	
+	cpCollisionHandler *handler = arb->handler;
+	
+	// Call the begin function first if it's the first step
+	if(arb->state == CP_ARBITER_STATE_FIRST_COLLISION && !handler->beginFunc(arb, space, handler->userData)){
+		cpArbiterIgnore(arb); // permanently ignore the collision until separation
+	}
+	
+	if(
+		// Ignore the arbiter if it has been flagged
+		(arb->state != CP_ARBITER_STATE_IGNORE) && 
+		// Call preSolve
+		handler->preSolveFunc(arb, space, handler->userData) &&
+		// Check (again) in case the pre-solve() callback called cpArbiterIgnored().
+		arb->state != CP_ARBITER_STATE_IGNORE &&
+		// Process, but don't add collisions for sensors.
+		!(a->sensor || b->sensor) &&
+		// Don't process collisions between two infinite mass bodies.
+		// This includes collisions between two kinematic bodies, or a kinematic body and a static body.
+		!(a->body->m == INFINITY && b->body->m == INFINITY)
+	){
+		cpArrayPush(space->arbiters, arb);
+	} else {
+		cpSpacePopContacts(space, info.count);
+		
+		arb->contacts = NULL;
+		arb->count = 0;
+		
+		// Normally arbiters are set as used after calling the post-solve callback.
+		// However, post-solve() callbacks are not called for sensors or arbiters rejected from pre-solve.
+		if(arb->state != CP_ARBITER_STATE_IGNORE) arb->state = CP_ARBITER_STATE_NORMAL;
+	}
+	
+	// Time stamp the arbiter so we know it was used recently.
+	arb->stamp = space->stamp;
+	return info.id;
+}
+
+// Hashset filter func to throw away old arbiters.
+cpBool
+cpSpaceArbiterSetFilter(cpArbiter *arb, cpSpace *space)
+{
+	cpTimestamp ticks = space->stamp - arb->stamp;
+	
+	cpBody *a = arb->body_a, *b = arb->body_b;
+	
+	// TODO: should make an arbiter state for this so it doesn't require filtering arbiters for dangling body pointers on body removal.
+	// Preserve arbiters on sensors and rejected arbiters for sleeping objects.
+	// This prevents errant separate callbacks from happenening.
+	if(
+		(cpBodyGetType(a) == CP_BODY_TYPE_STATIC || cpBodyIsSleeping(a)) &&
+		(cpBodyGetType(b) == CP_BODY_TYPE_STATIC || cpBodyIsSleeping(b))
+	){
+		return cpTrue;
+	}
+	
+	// Arbiter was used last frame, but not this one
+	if(ticks >= 1 && arb->state != CP_ARBITER_STATE_CACHED){
+		arb->state = CP_ARBITER_STATE_CACHED;
+		cpCollisionHandler *handler = arb->handler;
+		handler->separateFunc(arb, space, handler->userData);
+	}
+	
+	if(ticks >= space->collisionPersistence){
+		arb->contacts = NULL;
+		arb->count = 0;
+		
+		cpArrayPush(space->pooledArbiters, arb);
+		return cpFalse;
+	}
+	
+	return cpTrue;
+}
+
+//MARK: All Important cpSpaceStep() Function
+
+ void
+cpShapeUpdateFunc(cpShape *shape, void *unused)
+{
+	cpShapeCacheBB(shape);
+}
+
+void
+cpSpaceStep(cpSpace *space, cpFloat dt)
+{
+	// don't step if the timestep is 0!
+	if(dt == 0.0f) return;
+	
+	space->stamp++;
+	
+	cpFloat prev_dt = space->curr_dt;
+	space->curr_dt = dt;
+		
+	cpArray *bodies = space->dynamicBodies;
+	cpArray *constraints = space->constraints;
+	cpArray *arbiters = space->arbiters;
+	
+	// Reset and empty the arbiter lists.
+	for(int i=0; i<arbiters->num; i++){
+		cpArbiter *arb = (cpArbiter *)arbiters->arr[i];
+		arb->state = CP_ARBITER_STATE_NORMAL;
+		
+		// If both bodies are awake, unthread the arbiter from the contact graph.
+		if(!cpBodyIsSleeping(arb->body_a) && !cpBodyIsSleeping(arb->body_b)){
+			cpArbiterUnthread(arb);
+		}
+	}
+	arbiters->num = 0;
+
+	cpSpaceLock(space); {
+		// Integrate positions
+		for(int i=0; i<bodies->num; i++){
+			cpBody *body = (cpBody *)bodies->arr[i];
+			body->position_func(body, dt);
+		}
+		
+		// Find colliding pairs.
+		cpSpacePushFreshContactBuffer(space);
+		cpSpatialIndexEach(space->dynamicShapes, (cpSpatialIndexIteratorFunc)cpShapeUpdateFunc, NULL);
+		cpSpatialIndexReindexQuery(space->dynamicShapes, (cpSpatialIndexQueryFunc)cpSpaceCollideShapes, space);
+	} cpSpaceUnlock(space, cpFalse);
+	
+	// Rebuild the contact graph (and detect sleeping components if sleeping is enabled)
+	cpSpaceProcessComponents(space, dt);
+	
+	cpSpaceLock(space); {
+		// Clear out old cached arbiters and call separate callbacks
+		cpHashSetFilter(space->cachedArbiters, (cpHashSetFilterFunc)cpSpaceArbiterSetFilter, space);
+
+		// Prestep the arbiters and constraints.
+		cpFloat slop = space->collisionSlop;
+		cpFloat biasCoef = 1.0f - cpfpow(space->collisionBias, dt);
+		for(int i=0; i<arbiters->num; i++){
+			cpArbiterPreStep((cpArbiter *)arbiters->arr[i], dt, slop, biasCoef);
+		}
+
+		for(int i=0; i<constraints->num; i++){
+			cpConstraint *constraint = (cpConstraint *)constraints->arr[i];
+			
+			cpConstraintPreSolveFunc preSolve = constraint->preSolve;
+			if(preSolve) preSolve(constraint, space);
+			
+			constraint->klass->preStep(constraint, dt);
+		}
+	
+		// Integrate velocities.
+		cpFloat damping = cpfpow(space->damping, dt);
+		cpVect gravity = space->gravity;
+		for(int i=0; i<bodies->num; i++){
+			cpBody *body = (cpBody *)bodies->arr[i];
+			body->velocity_func(body, gravity, damping, dt);
+		}
+		
+		// Apply cached impulses
+		cpFloat dt_coef = (prev_dt == 0.0f ? 0.0f : dt/prev_dt);
+		for(int i=0; i<arbiters->num; i++){
+			cpArbiterApplyCachedImpulse((cpArbiter *)arbiters->arr[i], dt_coef);
+		}
+		
+		for(int i=0; i<constraints->num; i++){
+			cpConstraint *constraint = (cpConstraint *)constraints->arr[i];
+			constraint->klass->applyCachedImpulse(constraint, dt_coef);
+		}
+		
+		// Run the impulse solver.
+		for(int i=0; i<space->iterations; i++){
+			for(int j=0; j<arbiters->num; j++){
+				cpArbiterApplyImpulse((cpArbiter *)arbiters->arr[j]);
+			}
+				
+			for(int j=0; j<constraints->num; j++){
+				cpConstraint *constraint = (cpConstraint *)constraints->arr[j];
+				constraint->klass->applyImpulse(constraint, dt);
+			}
+		}
+		
+		// Run the constraint post-solve callbacks
+		for(int i=0; i<constraints->num; i++){
+			cpConstraint *constraint = (cpConstraint *)constraints->arr[i];
+			
+			cpConstraintPostSolveFunc postSolve = constraint->postSolve;
+			if(postSolve) postSolve(constraint, space);
+		}
+		
+		// run the post-solve callbacks
+		for(int i=0; i<arbiters->num; i++){
+			cpArbiter *arb = (cpArbiter *) arbiters->arr[i];
+			
+			cpCollisionHandler *handler = arb->handler;
+			handler->postSolveFunc(arb, space, handler->userData);
+		}
+	} cpSpaceUnlock(space, cpTrue);
+}
diff --git a/Chipmunk2D-7.0.2/src/cpSpatialIndex.c b/Chipmunk2D-7.0.2/src/cpSpatialIndex.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpSpatialIndex.c
@@ -0,0 +1,69 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+void
+cpSpatialIndexFree(cpSpatialIndex *index)
+{
+	if(index){
+		cpSpatialIndexDestroy(index);
+		cpfree(index);
+	}
+}
+
+cpSpatialIndex *
+cpSpatialIndexInit(cpSpatialIndex *index, cpSpatialIndexClass *klass, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
+{
+	index->klass = klass;
+	index->bbfunc = bbfunc;
+	index->staticIndex = staticIndex;
+	
+	if(staticIndex){
+		cpAssertHard(!staticIndex->dynamicIndex, "This static index is already associated with a dynamic index.");
+		staticIndex->dynamicIndex = index;
+	}
+	
+	return index;
+}
+
+typedef struct dynamicToStaticContext {
+	cpSpatialIndexBBFunc bbfunc;
+	cpSpatialIndex *staticIndex;
+	cpSpatialIndexQueryFunc queryFunc;
+	void *data;
+} dynamicToStaticContext;
+
+static void
+dynamicToStaticIter(void *obj, dynamicToStaticContext *context)
+{
+	cpSpatialIndexQuery(context->staticIndex, obj, context->bbfunc(obj), context->queryFunc, context->data);
+}
+
+void
+cpSpatialIndexCollideStatic(cpSpatialIndex *dynamicIndex, cpSpatialIndex *staticIndex, cpSpatialIndexQueryFunc func, void *data)
+{
+	if(staticIndex && cpSpatialIndexCount(staticIndex) > 0){
+		dynamicToStaticContext context = {dynamicIndex->bbfunc, staticIndex, func, data};
+		cpSpatialIndexEach(dynamicIndex, (cpSpatialIndexIteratorFunc)dynamicToStaticIter, &context);
+	}
+}
+
diff --git a/Chipmunk2D-7.0.2/src/cpSweep1D.c b/Chipmunk2D-7.0.2/src/cpSweep1D.c
new file mode 100644
--- /dev/null
+++ b/Chipmunk2D-7.0.2/src/cpSweep1D.c
@@ -0,0 +1,254 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static inline cpSpatialIndexClass *Klass();
+
+//MARK: Basic Structures
+
+typedef struct Bounds {
+	cpFloat min, max;
+} Bounds;
+
+typedef struct TableCell {
+	void *obj;
+	Bounds bounds;
+} TableCell;
+
+struct cpSweep1D
+{
+	cpSpatialIndex spatialIndex;
+	
+	int num;
+	int max;
+	TableCell *table;
+};
+
+static inline cpBool
+BoundsOverlap(Bounds a, Bounds b)
+{
+	return (a.min <= b.max && b.min <= a.max);
+}
+
+static inline Bounds
+BBToBounds(cpSweep1D *sweep, cpBB bb)
+{
+	Bounds bounds = {bb.l, bb.r};
+	return bounds;
+}
+
+static inline TableCell
+MakeTableCell(cpSweep1D *sweep, void *obj)
+{
+	TableCell cell = {obj, BBToBounds(sweep, sweep->spatialIndex.bbfunc(obj))};
+	return cell;
+}
+
+//MARK: Memory Management Functions
+
+cpSweep1D *
+cpSweep1DAlloc(void)
+{
+	return (cpSweep1D *)cpcalloc(1, sizeof(cpSweep1D));
+}
+
+static void
+ResizeTable(cpSweep1D *sweep, int size)
+{
+	sweep->max = size;
+	sweep->table = (TableCell *)cprealloc(sweep->table, size*sizeof(TableCell));
+}
+
+cpSpatialIndex *
+cpSweep1DInit(cpSweep1D *sweep, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
+{
+	cpSpatialIndexInit((cpSpatialIndex *)sweep, Klass(), bbfunc, staticIndex);
+	
+	sweep->num = 0;
+	ResizeTable(sweep, 32);
+	
+	return (cpSpatialIndex *)sweep;
+}
+
+cpSpatialIndex *
+cpSweep1DNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
+{
+	return cpSweep1DInit(cpSweep1DAlloc(), bbfunc, staticIndex);
+}
+
+static void
+cpSweep1DDestroy(cpSweep1D *sweep)
+{
+	cpfree(sweep->table);
+	sweep->table = NULL;
+}
+
+//MARK: Misc
+
+static int
+cpSweep1DCount(cpSweep1D *sweep)
+{
+	return sweep->num;
+}
+
+static void
+cpSweep1DEach(cpSweep1D *sweep, cpSpatialIndexIteratorFunc func, void *data)
+{
+	TableCell *table = sweep->table;
+	for(int i=0, count=sweep->num; i<count; i++) func(table[i].obj, data);
+}
+
+static int
+cpSweep1DContains(cpSweep1D *sweep, void *obj, cpHashValue hashid)
+{
+	TableCell *table = sweep->table;
+	for(int i=0, count=sweep->num; i<count; i++){
+		if(table[i].obj == obj) return cpTrue;
+	}
+	
+	return cpFalse;
+}
+
+//MARK: Basic Operations
+
+static void
+cpSweep1DInsert(cpSweep1D *sweep, void *obj, cpHashValue hashid)
+{
+	if(sweep->num == sweep->max) ResizeTable(sweep, sweep->max*2);
+	
+	sweep->table[sweep->num] = MakeTableCell(sweep, obj);
+	sweep->num++;
+}
+
+static void
+cpSweep1DRemove(cpSweep1D *sweep, void *obj, cpHashValue hashid)
+{
+	TableCell *table = sweep->table;
+	for(int i=0, count=sweep->num; i<count; i++){
+		if(table[i].obj == obj){
+			int num = --sweep->num;
+			
+			table[i] = table[num];
+			table[num].obj = NULL;
+			
+			return;
+		}
+	}
+}
+
+//MARK: Reindexing Functions
+
+static void
+cpSweep1DReindexObject(cpSweep1D *sweep, void *obj, cpHashValue hashid)
+{
+	// Nothing to do here
+}
+
+static void
+cpSweep1DReindex(cpSweep1D *sweep)
+{
+	// Nothing to do here
+	// Could perform a sort, but queries are not accelerated anyway.
+}
+
+//MARK: Query Functions
+
+static void
+cpSweep1DQuery(cpSweep1D *sweep, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data)
+{
+	// Implementing binary search here would allow you to find an upper limit
+	// but not a lower limit. Probably not worth the hassle.
+	
+	Bounds bounds = BBToBounds(sweep, bb);
+	
+	TableCell *table = sweep->table;
+	for(int i=0, count=sweep->num; i<count; i++){
+		TableCell cell = table[i];
+		if(BoundsOverlap(bounds, cell.bounds) && obj != cell.obj) func(obj, cell.obj, 0, data);
+	}
+}
+
+static void
+cpSweep1DSegmentQuery(cpSweep1D *sweep, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data)
+{
+	cpBB bb = cpBBExpand(cpBBNew(a.x, a.y, a.x, a.y), b);
+	Bounds bounds = BBToBounds(sweep, bb);
+	
+	TableCell *table = sweep->table;
+	for(int i=0, count=sweep->num; i<count; i++){
+		TableCell cell = table[i];
+		if(BoundsOverlap(bounds, cell.bounds)) func(obj, cell.obj, data);
+	}
+}
+
+//MARK: Reindex/Query
+
+static int
+TableSort(TableCell *a, TableCell *b)
+{
+	return (a->bounds.min < b->bounds.min ? -1 : (a->bounds.min > b->bounds.min ? 1 : 0));
+}
+
+static void
+cpSweep1DReindexQuery(cpSweep1D *sweep, cpSpatialIndexQueryFunc func, void *data)
+{
+	TableCell *table = sweep->table;
+	int count = sweep->num;
+	
+	// Update bounds and sort
+	for(int i=0; i<count; i++) table[i] = MakeTableCell(sweep, table[i].obj);
+	qsort(table, count, sizeof(TableCell), (int (*)(const void *, const void *))TableSort); // TODO: use insertion sort instead
+	
+	for(int i=0; i<count; i++){
+		TableCell cell = table[i];
+		cpFloat max = cell.bounds.max;
+		
+		for(int j=i+1; table[j].bounds.min < max && j<count; j++){
+			func(cell.obj, table[j].obj, 0, data);
+		}
+	}
+	
+	// Reindex query is also responsible for colliding against the static index.
+	// Fortunately there is a helper function for that.
+	cpSpatialIndexCollideStatic((cpSpatialIndex *)sweep, sweep->spatialIndex.staticIndex, func, data);
+}
+
+static cpSpatialIndexClass klass = {
+	(cpSpatialIndexDestroyImpl)cpSweep1DDestroy,
+	
+	(cpSpatialIndexCountImpl)cpSweep1DCount,
+	(cpSpatialIndexEachImpl)cpSweep1DEach,
+	(cpSpatialIndexContainsImpl)cpSweep1DContains,
+	
+	(cpSpatialIndexInsertImpl)cpSweep1DInsert,
+	(cpSpatialIndexRemoveImpl)cpSweep1DRemove,
+	
+	(cpSpatialIndexReindexImpl)cpSweep1DReindex,
+	(cpSpatialIndexReindexObjectImpl)cpSweep1DReindexObject,
+	(cpSpatialIndexReindexQueryImpl)cpSweep1DReindexQuery,
+	
+	(cpSpatialIndexQueryImpl)cpSweep1DQuery,
+	(cpSpatialIndexSegmentQueryImpl)cpSweep1DSegmentQuery,
+};
+
+static inline cpSpatialIndexClass *Klass(){return &klass;}
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Cthulhu (c) 2018
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Cthulhu nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+# chiphunk
+
+Chiphunk is a Haskell bindings for Chipmunk2D physics library. See `Chiphunk.Low` module for documentation.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/app/Main.hs b/app/Main.hs
new file mode 100644
--- /dev/null
+++ b/app/Main.hs
@@ -0,0 +1,168 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedStrings #-}
+module Main where
+
+import Chiphunk.Low
+import Data.Functor
+import Text.Printf (printf)
+import Control.Monad
+import Control.Concurrent.MVar
+import Control.Concurrent (threadDelay)
+import Control.Concurrent.Async
+
+import qualified Graphics.NanoVG.Simple as N
+import qualified Graphics.NanoVG.Picture as N
+import qualified NanoVG                 as NVG
+import           Data.IORef
+
+main :: IO ()
+main = do
+  dm <- newEmptyMVar
+  race_
+    (simulate dm)
+    (display dm)
+
+simulate :: MVar [VisObj] -> IO ()
+simulate dm = do
+  let gravity = Vect 0 (-100)
+  -- Create an empty space.
+  space <- spaceNew
+  spaceGravity space $= gravity
+
+  static <- get $ spaceStaticBody space
+
+  -- Add a static line segment shape for the ground.
+  -- We'll make it slightly tilted so the ball will roll off.
+  -- We attach it to a static body to tell Chipmunk it shouldn't be movable.
+  let (segA, segB) = (Vect (-20) (-5), Vect 20 (-25))
+  ground <- segmentShapeNew static segA segB 0
+  shapeElasticity ground $= 0.6
+  shapeFriction ground $= 1
+
+  spaceAddShape space ground
+
+  -- Now let's make a ball that falls onto the line and rolls off.
+  -- First we need to make a cpBody to hold the physical properties of the object.
+  -- These include the mass, position, velocity, angle, etc. of the object.
+  -- Then we attach collision shapes to the cpBody to give it a size and shape.
+
+  let radius = 5
+  let mass = 1
+  let mass100 = 100
+
+  -- The moment of inertia is like mass for rotation
+  -- Use the cpMomentFor*() functions to help you approximate it.
+  let moment = momentForCircle mass 0 radius (Vect 0 0)
+  let moment100 = momentForCircle mass100 0 radius (Vect 0 0)
+
+  -- The cpSpaceAdd*() functions return the thing that you are adding.
+  -- It's convenient to create and add an object in one line.
+  ballBody <- bodyNew mass moment
+  spaceAddBody space ballBody
+
+  -- Now we create the collision shape for the ball.
+  -- You can create multiple collision shapes that point to the same body.
+  -- They will all be attached to the body and move around to follow it.
+  ballShape <- circleShapeNew ballBody radius (Vect 0 0)
+  shapeFriction ballShape $= 0.9
+  shapeElasticity ballShape $= 1
+  spaceAddShape space ballShape
+
+  anotherBall <- bodyNew mass100 moment100
+  spaceAddBody space anotherBall
+
+  anotherBallShape <- circleShapeNew anotherBall radius (Vect 0 0)
+  shapeFriction anotherBallShape $= 0.9
+  shapeElasticity anotherBallShape $= 0.4
+  spaceAddShape space anotherBallShape
+
+  putMVar dm
+    [ mkStaticObj $ Segment segA segB
+    , mkBallBody ballBody radius
+    , mkBallBody anotherBall radius
+    ]
+
+  void $ forever $ do
+    bodyPosition ballBody $= Vect (-15) 30
+    bodyPosition anotherBall $= Vect (-5) 75
+    -- need to reset ball velocity after previous iteration
+    bodyVelocity ballBody $= Vect 0 0
+    bodyAngularVelocity ballBody $= 0
+    bodyVelocity anotherBall $= Vect 0 0
+    bodyAngularVelocity anotherBall $= 0
+
+    -- Now that it's all set up, we simulate all the objects in the space by
+    -- stepping forward through time in small increments called steps.
+    -- It is *highly* recommended to use a fixed size time step.
+    let timeStep = 1/60
+    runFor 3 timeStep $ \time -> do
+      pos <- get $ bodyPosition ballBody
+      vel <- get $ bodyVelocity ballBody
+      printf "Time is %4.2f. ballBody is at (%6.2f, %6.2f), it's velocity is (%6.2f, %6.2f).\n"
+             time (vX pos) (vY pos) (vX vel) (vY vel)
+
+      threadDelay $ round $ timeStep * 1000 * 1000
+      spaceStep space timeStep
+
+  shapeFree ballShape
+  bodyFree ballBody
+  shapeFree ground
+  spaceFree space
+  where
+    runFor time step inner = go time
+      where
+        go time'
+          | time' <= 0 = pure ()
+          | otherwise  = inner (time - time') *> go (time' - step)
+
+display :: MVar [VisObj] -> IO ()
+display dm = do
+  d <- takeMVar dm
+  N.run 800 600 "Chiphunk" $
+    N.showFPS "Liberation Sans" $
+    N.loadFont "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf" "Liberation Sans" $
+    N.asWindow $
+      N.translateP 400 300 .
+      N.scaleP' (0, 0) 10 .
+      N.scalePy (0, 0) (-1) .
+      N.pictures <$>
+        sequence ((render <$>) . runVisObj <$> d)
+  where
+    render = \case
+      Segment (Vect ax ay) (Vect bx by) -> N.stroke (NVG.Color 1 1 1 1) $
+        N.line (realToFrac ax, realToFrac ay) (realToFrac bx, realToFrac by)
+      Ball (Vect x y) r a ->
+        let c = (realToFrac x, realToFrac y)
+        in N.stroke (NVG.Color 1 1 1 1) $
+            N.rotateS c (realToFrac a) $
+            N.shapes
+              [ N.circle c (realToFrac r)
+              , N.line c (realToFrac $ x - r / 2, realToFrac y)
+              ]
+
+data VisShape =
+    Segment
+    { segEndpointA :: Vect
+    , segEndpointB :: Vect
+    }
+  | Ball
+    { ballCenter :: Vect
+    , ballRadius :: Double
+    , ballAngle :: Double
+    }
+  deriving Show
+
+newtype VisObj = VisObj
+  { runVisObj :: IO VisShape
+  }
+
+mkRefObj :: IORef VisShape -> VisObj
+mkRefObj r = VisObj $ readIORef r
+
+mkStaticObj :: VisShape -> VisObj
+mkStaticObj = VisObj . pure
+
+mkBallBody :: Body -> Double -> VisObj
+mkBallBody b r = VisObj $ Ball <$> get (bodyPosition b)
+                               <*> pure r
+                               <*> get (bodyAngle b)
diff --git a/chiphunk.cabal b/chiphunk.cabal
new file mode 100644
--- /dev/null
+++ b/chiphunk.cabal
@@ -0,0 +1,137 @@
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.30.0.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: 6654f10bfcf93a216508e1f3fa7c6a251033427487355ade61c5dea7ad87e255
+
+name:           chiphunk
+version:        0.1.0.0
+synopsis:       Haskell bindings for Chipmunk2D physics engine
+description:    Please see the README on GitHub at <https://github.com/CthulhuDen/chiphunk#readme>
+category:       Physics
+homepage:       https://github.com/CthulhuDen/chiphunk#readme
+author:         Cthulhu
+maintainer:     cthulhu.den@gmail.com
+copyright:      Cthulhu (c) 2018
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+extra-source-files:
+    README.md
+    Chipmunk2D-7.0.2/include/chipmunk/chipmunk_ffi.h
+    Chipmunk2D-7.0.2/include/chipmunk/chipmunk.h
+    Chipmunk2D-7.0.2/include/chipmunk/chipmunk_private.h
+    Chipmunk2D-7.0.2/include/chipmunk/chipmunk_structs.h
+    Chipmunk2D-7.0.2/include/chipmunk/chipmunk_types.h
+    Chipmunk2D-7.0.2/include/chipmunk/chipmunk_unsafe.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpArbiter.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpBB.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpBody.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpConstraint.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpDampedRotarySpring.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpDampedSpring.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpGearJoint.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpGrooveJoint.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpHastySpace.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpMarch.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpPinJoint.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpPivotJoint.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpPolyline.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpPolyShape.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpRatchetJoint.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpRobust.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpRotaryLimitJoint.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpShape.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpSimpleMotor.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpSlideJoint.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpSpace.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpSpatialIndex.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpTransform.h
+    Chipmunk2D-7.0.2/include/chipmunk/cpVect.h
+
+flag library-only
+  manual: False
+  default: True
+
+library
+  exposed-modules:
+      Chiphunk.Low
+  other-modules:
+      Chiphunk.Low.Math
+      Chiphunk.Low.Types
+      Chiphunk.Low.Internal
+      Chiphunk.Low.Helper
+      Chiphunk.Low.Vect
+      Chiphunk.Low.BB
+      Chiphunk.Low.Body
+      Chiphunk.Low.Shape
+      Chiphunk.Low.Space
+      Chiphunk.Low.Constraint
+      Chiphunk.Low.Callback
+      Chiphunk.Low.Arbiter
+  hs-source-dirs:
+      src
+  ghc-options: -Wall
+  include-dirs:
+      Chipmunk2D-7.0.2/include
+      src/Chiphunk
+  c-sources:
+      Chipmunk2D-7.0.2/src/chipmunk.c
+      Chipmunk2D-7.0.2/src/cpConstraint.c
+      Chipmunk2D-7.0.2/src/cpSpaceStep.c
+      Chipmunk2D-7.0.2/src/cpShape.c
+      Chipmunk2D-7.0.2/src/cpSpace.c
+      Chipmunk2D-7.0.2/src/cpArbiter.c
+      Chipmunk2D-7.0.2/src/cpArray.c
+      Chipmunk2D-7.0.2/src/cpBBTree.c
+      Chipmunk2D-7.0.2/src/cpBody.c
+      Chipmunk2D-7.0.2/src/cpCollision.c
+      Chipmunk2D-7.0.2/src/cpDampedRotarySpring.c
+      Chipmunk2D-7.0.2/src/cpDampedSpring.c
+      Chipmunk2D-7.0.2/src/cpGearJoint.c
+      Chipmunk2D-7.0.2/src/cpGrooveJoint.c
+      Chipmunk2D-7.0.2/src/cpHashSet.c
+      Chipmunk2D-7.0.2/src/cpHastySpace.c
+      Chipmunk2D-7.0.2/src/cpMarch.c
+      Chipmunk2D-7.0.2/src/cpPinJoint.c
+      Chipmunk2D-7.0.2/src/cpPivotJoint.c
+      Chipmunk2D-7.0.2/src/cpPolyline.c
+      Chipmunk2D-7.0.2/src/cpPolyShape.c
+      Chipmunk2D-7.0.2/src/cpRatchetJoint.c
+      Chipmunk2D-7.0.2/src/cpRobust.c
+      Chipmunk2D-7.0.2/src/cpRotaryLimitJoint.c
+      Chipmunk2D-7.0.2/src/cpSimpleMotor.c
+      Chipmunk2D-7.0.2/src/cpSlideJoint.c
+      Chipmunk2D-7.0.2/src/cpSpaceComponent.c
+      Chipmunk2D-7.0.2/src/cpSpaceDebug.c
+      Chipmunk2D-7.0.2/src/cpSpaceHash.c
+      Chipmunk2D-7.0.2/src/cpSpaceQuery.c
+      Chipmunk2D-7.0.2/src/cpSpatialIndex.c
+      Chipmunk2D-7.0.2/src/cpSweep1D.c
+      
+      src/Chiphunk/wrapper.c
+  build-depends:
+      StateVar >=1.1.1.1 && <1.2
+    , base >=4.7 && <5
+    , safe-exceptions >=0.1.7.0 && <0.2
+    , vector-space >=0.13 && <0.16
+  default-language: Haskell2010
+
+executable chiphunk
+  main-is: Main.hs
+  other-modules:
+      Paths_chiphunk
+  hs-source-dirs:
+      app
+  ghc-options: -Wall -O2 -threaded -rtsopts -with-rtsopts=-N2
+  build-depends:
+      async >=2.2.1 && <2.3
+    , base >=4.7 && <5
+    , chiphunk
+    , nanovg >=0.6.0.0 && <0.7
+    , nanovg-simple >=0.4.0.0 && <0.5
+  if flag(library-only)
+    buildable: False
+  default-language: Haskell2010
diff --git a/src/Chiphunk/Low.hs b/src/Chiphunk/Low.hs
new file mode 100644
--- /dev/null
+++ b/src/Chiphunk/Low.hs
@@ -0,0 +1,998 @@
+-- | Description: Low-level Haskell bindings to Chipmunk2D physics library
+-- Chiphunk is a __low-level__ Haskell bindings for the <https://chipmunk-physics.net/ Chipmunk2D physics engine>.
+-- It includes most (almost all) of the functions mentioned in the main documentation for Chipmunk2D,
+-- except for some (relatively) exotic ones, which may be added later per request.
+module Chiphunk.Low
+  ( -- * Disclaymer
+
+    -- | This bindings are so low-level so that they even require you to free the memory the Chipmunk2D has allocated
+    -- for your objects. Module with more high-level api can be built around this low-level bingings at some point,
+    -- in the meantime, however, you're advised to provide wrapper layer for your games so that you do not have to
+    -- keep track of such things in the core of your game's logic.
+    --
+    -- See below for an adoptation of the original Chipmunk documentation available
+    -- <https://chipmunk-physics.net/release/ChipmunkLatest-Docs/ here>. I've skipped some sections not related
+    -- to the bindings, like the reason author chose C language in the first place and limitations of the C api.
+    -- Obviously, it's thanks to that choice that I was able to write bindings around the library in Haskell.
+    --
+    -- __Howling Moon Software is not affiliated with this bindings.__
+    -- __In all of the following \"I\" refers to the original documentation author for Chipmunk2D.__
+
+    -- * Chipmunk2D 7.0.2
+
+    -- | Chipmunk2D is a 2D rigid body physics library distributed under the MIT license.
+    -- It is blazingly fast, portable, numerically stable, and easy to use.
+    -- For this reason it has been used in hundreds of games across just about every system you can name.
+    -- This includes top quality titles such as Night Sky for the Wii and many #1 sellers on the iPhone App Store!
+    -- I’ve put thousands of hours of work over many years to make Chipmunk2D what it is today.
+    -- If you find Chipmunk2D has saved you a lot of time, please consider
+    -- <https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6666552 donating>.
+    -- You’ll make an indie game developer very happy!
+
+    -- | First of all, I would like to give a Erin Catto a big thank you, as Chipmunk2D’s impulse solver
+    -- was directly inspired by his example code way back in 2006.
+    -- (Now a full fledged physics engine all its own: <http://www.box2d.org/ Box2D.org>).
+    -- His contact persistence idea allows for stable stacks of objects with very few iterations of the solver.
+    -- My previous solver produced mushy piles of objects or required a large amount of CPU to operate stably.
+
+    -- ** Support
+
+    -- | The best way to get support is to visit the <http://www.slembcke.net/forums/viewforum.php?f=1 Chipmunk Forums>.
+    -- There are plenty of people around using Chipmunk on the just about every platform
+    -- I’ve ever heard of. If you are working on a commercial project, Howling Moon Software
+    -- (my company) is <http://howlingmoonsoftware.com/contracting.php available for contracting>.
+    -- We can help with implementing custom Chipmunk behaviors,
+    -- as well as priority bug fixes and performance tuning.
+
+    -- ** Contact
+
+    -- | If you find any bugs in Chipmunk, errors or broken links in this document,
+    -- or have a question or comment about Chipmunk you can contact me at
+    -- slembcke(at)gmail(dot)com. (email or GTalk)
+
+    -- ** License
+
+    -- | Chipmunk is licensed under the MIT license.
+    --
+    -- @
+    -- Copyright (c) 2007-2015 Scott Lembcke and Howling Moon Software
+    --
+    -- Permission is hereby granted, free of charge, to any person obtaining a copy
+    -- of this software and associated documentation files (the "Software"), to deal
+    -- in the Software without restriction, including without limitation the rights
+    -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    -- copies of the Software, and to permit persons to whom the Software is
+    -- furnished to do so, subject to the following conditions:
+    --
+    -- The above copyright notice and this permission notice shall be included in
+    -- all copies or substantial portions of the Software.
+    --
+    -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+    -- SOFTWARE.
+    -- @
+    --
+    -- This means that you do not have to buy a license or pay to use Chipmunk in commercial projects. (Though we really appreciate donations)
+
+    -- ** Links
+
+    -- |
+    -- * <http://chipmunk2d.net/forum Chipmunk Forums> – The official forum Chipmunk2D forum.
+    --
+    -- * <http://howlingmoonsoftware.com/ Howling Moon Software> – The software company I co-founded.
+    -- (We are available for contract work!)
+    --
+    -- * <http://chipmunk2d.net/games.php Games> – A small list of games we know that use Chipmunk.
+
+    -- * Hello Chipmunk (World)
+
+    -- | Hello world Chipmunk style. Create a simple simulation where a ball falls onto a static line segment,
+    -- then rolls off. Print out the coordinates of the ball.
+    --
+    -- @
+    -- main :: IO ()
+    -- main = do
+    --   let gravity = 'Vect' 0 (-100)
+    --
+    --   -- Create an empty space.
+    --   space <- 'spaceNew'
+    --   'spaceGravity' space $= gravity
+    --
+    --   -- Add a static line segment shape for the ground.
+    --   -- We'll make it slightly tilted so the ball will roll off.
+    --   -- We attach it to a static body to tell Chipmunk it shouldn't be movable.
+    --   static <- get $ 'spaceStaticBody' space
+    --   ground <- 'segmentShapeNew' static (Vect (-20) 5) (Vect 20 (-5)) 0
+    --   'shapeFriction' ground $= 1
+    --   'spaceAddShape' space ground
+    --
+    --   -- Now let's make a ball that falls onto the line and rolls off.
+    --   -- First we need to make a cpBody to hold the physical properties of the object.
+    --   -- These include the mass, position, velocity, angle, etc. of the object.
+    --   -- Then we attach collision shapes to the 'Body' to give it a size and shape.
+    --
+    --   let radius = 5
+    --   let mass = 1
+    --
+    --   -- The moment of inertia is like mass for rotation
+    --   -- Use the momentFor* functions to help you approximate it.
+    --   let moment = 'momentForCircle' mass 0 radius (Vect 0 0)
+    --
+    --   -- The spaceAdd* functions return the thing that you are adding.
+    --   ballBody <- 'bodyNew' mass moment
+    --   'spaceAddBody' space ballBody
+    --   'bodyPosition' ballBody $= Vect 0 15
+    --
+    --   -- Now we create the collision shape for the ball.
+    --   -- You can create multiple collision shapes that point to the same body.
+    --   -- They will all be attached to the body and move around to follow it.
+    --   ballShape <- 'circleShapeNew' ballBody radius (Vect 0 0)
+    --   'spaceAddShape' space ballShape
+    --   'shapeFriction' ballShape $= 0.7
+    --
+    --   -- Now that it's all set up, we simulate all the objects in the space by
+    --   -- stepping forward through time in small increments called steps.
+    --   -- It is *highly* recommended to use a fixed size time step.
+    --   let timeStep = 1/60
+    --   runFor 2 timeStep $ \time -> do
+    --     pos <- get $ 'bodyPosition' ballBody
+    --     vel <- get $ 'bodyVelocity' ballBody
+    --     printf "Time is %4.2f. ballBody is at (%6.2f, %6.2f), it's velocity is (%6.2f, %6.2f).\n"
+    --            time (vX pos) (vY pos) (vX vel) (vY vel)
+    --
+    --     'spaceStep' space timeStep
+    --
+    --   'shapeFree' ballShape
+    --   'bodyFree' ballBody
+    --   'shapeFree' ground
+    --   'spaceFree' space
+    --   where
+    --     runFor time step inner = go time
+    --       where
+    --         go time'
+    --           | time' <= 0 = pure ()
+    --           | otherwise  = inner (time - time') *> go (time' - step)
+    -- @
+
+    -- * Chipmunk2D Basics
+
+    -- ** Overview
+
+    -- | There are 4 basic object types you will use in Chipmunk.
+
+    -- |
+    -- * __Rigid Bodies__ ('Body'): A rigid body holds the physical properties of an object.
+    -- (mass, position, rotation, velocity, etc.) It does not have a shape until you attach one or more collision shapes
+    -- to it. If you’ve done physics with particles before, rigid bodies differ in that they are able to rotate.
+    -- Rigid bodies generally tend to have a 1:1 correlation to sprites in a game.
+    -- You should structure your game so that you use the position and rotation of the rigid body
+    -- for drawing your sprite.
+    --
+    -- * __Collision Shapes__ ('Shape'): By attaching shapes to bodies, you can define the a body’s shape.
+    -- You can attach as many shapes to a single body as you need to in order to define a complex shape.
+    -- Shapes contain the surface properties of an object such as how much friction or elasticity it has.
+    --
+    -- * __Constraints/Joints__ ('Constraint'): Constraints and joints describe how bodies are attached to each other.
+    --
+    -- * __Spaces__ ('Space'): Spaces are containers for simulating objects in Chipmunk.
+    -- You add bodies, shapes and joints to a space and then update the space as a whole.
+    -- They control how all the rigid bodies, shapes, and constraints interact together.
+    --
+    -- There is often confusion between rigid bodies and their collision shapes in Chipmunk
+    -- and how they relate to sprites. A sprite would be a visual representation of an object,
+    -- while a collision shape is an invisible property that defines how objects should collide.
+    -- Both the sprite’s and the collision shape’s position and rotation are controlled by the motion of a rigid body.
+    -- Generally you want to create a game object type that ties these things all together.
+
+    -- ** Memory Management the Chipmunk way
+
+    -- | For most of the structures you will use, Chipmunk uses a more or less standard and straightforward set
+    -- of memory management functions. Take the 'Space' struct for example:
+    --
+    -- * 'spaceNew' — Allocates and initializes a 'Space' struct.
+    --
+    -- * 'spaceFree' — Destroys and frees the 'Space' struct.
+    --
+    -- You are responsible for freeing any structs that you allocate. Chipmunk does not do reference counting or garbage collection. If you call a new function, you must call the matching free function or you will leak memory.
+
+    -- ** Math the Chipmunk way
+
+    -- | First of all, Chipmunk uses double precision floating point numbers throughout its calculations by default.
+    -- This is likely to be faster on most modern desktop processors,
+    -- and means you don’t have to worry as much about floating point accuracy.
+    --
+    -- However, there are a few unique functions you will probably find very useful:
+    fClamp
+  , fLerp
+  , fLerpConst
+
+    -- * Chipmunk Vectors
+
+    -- ** Struct Definition, Constants and Constructors
+  , Vect (..)
+  , vZero
+  , cpv
+
+  -- ** Operations
+
+  -- | (__Note for bindings__: Most of these are Chipmunk2D-style aliases for 'Vect' typeclasses methods:
+  -- 'Eq', 'Data.VectorSpace.AdditiveGroup', 'Data.VectorSpace.VectorSpace', 'Data.VectorSpace.InnerSpace',
+  -- 'Data.Cross.HasCross2')
+  , vEql
+  , vAdd
+  , vSub
+  , vNeg
+  , vMult
+  , vDot
+  , vCross
+  , vPerp
+  , vRPerp
+  , vProject
+  , vRotate
+  , vUnRotate
+  , vLength
+  , vLengthSq
+  , vLerp
+  , vLerpConst
+  , vSLerp
+  , vSLerpConst
+  , vNormalize
+  , vClamp
+  , vDist
+  , vDistSq
+  , vNear
+  , vForAngle
+  , vToAngle
+
+    -- * Chipmunk Axis Aligned Bounding Boxes
+
+    -- ** Struct Definition and Constructors
+
+  , BB (..)
+  , bbNew
+  , bbNewForExtents
+  , bbNewForCircle
+
+    -- ** Operations
+
+  , bbIntersects
+  , bbContainsBB
+  , bbContainsVect
+  , bbMerge
+  , bbExpand
+  , bbCenter
+  , bbArea
+  , bbMergedArea
+  , bbSegmentQuery
+  , bbIntersectsSegment
+  , bbClampVect
+  , bbWrapVect
+
+    -- * Chipmunk Rigid Bodies
+  , Body
+
+    -- ** Dynamic, Kinematic, and Static Bodies
+  , BodyType (..)
+
+    -- ** Movement, Teleportation, and Velocity
+
+    -- | A graphics engine only needs to know the position of an object for each frame that its drawn.
+    -- For a physics engine, this isn’t enough information to calculate a collision response.
+    -- When you set the position of a body, you are effectively asking it to teleport itself.
+    -- This means that it will instantly move to its new position instead of moving through space and time
+    -- like a normal object. If you teleport an object so that it overlaps another one,
+    -- the best the physics engine can do is to attempt to push the objects apart again
+    -- since there is no information about their movement. This generally results in very mushy looking collisions.
+    -- So instead of setting the position of an object, it’s better to set its velocity and allow the physics engine
+    -- to update the position. That way it can resolve any resulting colisions natuarally since it knows
+    -- how the objects were moving. This is why kinematic bodies work the way they do.
+    -- You set the velocity, and the physics updates their position so the two are never out of sync.
+    --
+    -- For dynamic bodies, setting the velocity explicitly every frame can cause problems.
+    -- For example, a problem occurs when a light dynamic body (like a person) is pressed against a heavy dynamic body
+    -- (like a car), and you set velocity of the small object so that it’s pushing it into the big body.
+    -- To the physics engine, the change in velocity is the same as applying a large impulse
+    -- (a very short, very large force). Even if the velocity is low, the large force can allow the small body
+    -- to push the big body, even when it normally wouldn’t be able to. For example, a person walking into a car
+    -- can overpower the car’s friction and cause it to creep along the ground slowly.
+    -- Additionally, when you set the velocity of an object that is already in contact,
+    -- it can cause the two objects to overlap by a small amount. The easiest way to avoid both of these problems
+    -- is to make smaller changes to the body’s velocity, accelerating it over a fraction of a second
+    -- instead of a single frame. An even better solution, which is covered more thoroughly later,
+    -- is to use constraints to move the object.
+
+    -- ** Memory Management Functions
+
+    -- | Standard set of Chipmunk memory management functions.
+  , bodyNew
+  , bodyNewKinematic
+  , bodyNewStatic
+  , bodyFree
+
+    -- ** Creating Dynamic Bodies
+
+    -- | There are two ways to set up a dynamic body. The easiest option is to create a body
+    -- with a mass and moment of 0, and set the mass or density of each collision shape added to the body.
+    -- Chipmunk will automatically calculate the mass, moment of inertia, and center of gravity for you.
+    -- This is probably preferred in most cases.
+    --
+    -- The other option is to set the mass of the body when it’s created, and leave the mass of the shapes
+    -- added to it as 0.0. This approach is more flexible, but is not as easy to use.
+    -- __Don’t__ set the mass of both the body and the shapes. If you do so,
+    -- it will recalculate and overwite your custom mass value when the shapes are added to the body.
+
+    -- ** Properties
+
+    -- | Chipmunk provides getter/setter functions for a number of properties on rigid bodies.
+    -- Setting most properties automatically wakes the rigid bodies up if they were sleeping.
+
+  , bodyType
+  , bodyMass
+  , bodyMoment
+  , bodyPosition
+  , bodyCenterOfGravity
+  , bodyVelocity
+  , bodyForce
+  , bodyAngle
+  , bodyAngularVelocity
+  , bodyTorque
+  , bodyRotation
+  , bodySpace
+  , bodyUserData
+
+    -- ** Moment of Inertia and Area Helper Functions
+
+    -- | Use the following functions to approximate the moment of inertia for your body,
+    -- adding the results together if you want to use more than one.
+  , momentForCircle
+  , momentForSegment
+  , momentForPoly
+  , momentForBox
+
+    -- | Use the following functions to get the area for common Chipmunk shapes if you want to approximate masses
+    -- or density or whatnot.
+  , areaForCircle
+  , areaForSegment
+  , areaForPoly
+
+    -- ** Coordinate Conversion Functions
+
+    -- | Many things are defined in coordinates local to a body meaning that the (0,0) is at the center of gravity
+    -- of the body and the axis rotate along with the body.
+  , bodyLocalToWorld
+  , bodyWorldToLocal
+
+    -- ** Velocity Conversion Functions
+
+    -- | It’s often useful to know the absolute velocity of a point on the surface of a body
+    -- since the angular velocity affects everything except the center of gravity.
+  , bodyVelocityAtWorldPoint
+
+    -- ** Applying Forces and Torques
+
+    -- | People are sometimes confused by the difference between a force and an impulse.
+    -- An impulse is a very large force applied over a very short period of time.
+    -- Some examples are a ball hitting a wall or cannon firing. Chipmunk treats impulses as if they occur
+    -- instantaneously by adding directly to the velocity of an object.
+    -- Both impulses and forces are affected the mass of an object.
+    -- Doubling the mass of the object will halve the effect.
+  , bodyApplyForceAtWorldPoint
+  , bodyApplyForceAtLocalPoint
+  , bodyApplyImpulseAtWorldPoint
+  , bodyApplyImpulseAtLocalPoint
+
+    -- ** Sleeping Functions
+
+    -- | Chipmunk supports a sleeping feature which improves performance by not simulating groups of objects
+    -- that aren’t moving. Read more about it in the 'Space' section.
+  , bodyIsSleeping
+  , bodyActivate
+  , bodySleep
+  , bodyActivateStatic
+  , bodySleepWithGroup
+
+    -- ** Iterators
+  , BodyShapeIteratorFunc
+  , bodyEachShape
+  , BodyConstraintIteratorFunc
+  , bodyEachConstraint
+  , BodyArbiterIteratorFunc
+  , bodyEachArbiter
+
+    -- * Chipmunk Collision Shapes
+
+  , Shape
+
+    -- ** Properties
+
+    -- | Chipmunk provides getter/setter functions for a number of properties on collision shapes.
+    -- Setting most properties will automatically wake the attached rigid body, if it’s sleeping.
+
+  , shapeBody
+  , shapeBB
+  , shapeSensor
+  , shapeElasticity
+  , shapeFriction
+  , shapeSurfaceVelocity
+  , shapeCollisionType
+  , ShapeFilter (..)
+  , shapeFilter
+  , shapeSpace
+  , shapeUserData
+
+    -- ** Fast Collision Filtering using ShapeFilter
+
+    -- | Chipmunk has two primary means of ignoring collisions: groups and category masks.
+    --
+    -- __Groups__ are used to ignore collisions between parts on a complex object.
+    -- A ragdoll is a good example. When jointing an arm onto the torso, you’ll want them to allow them to overlap.
+    -- Groups allow you to do exactly that. Shapes that have the same group don’t generate collisions.
+    -- So by placing all of the shapes in a ragdoll in the same group, you’ll prevent it from colliding
+    -- against other parts of itself.
+    -- __Category__ masks allow you to mark which categories an object belongs to
+    -- and which categories it collidies with.
+    --
+    -- For example, a game has four collision categories: player (0), enemy (1), player bullet (2),
+    -- and enemy bullet (3). Neither players nor enemies should not collide with their own bullets,
+    -- and bullets should not collide with other bullets.
+    -- However, players collide with enemy bullets, and enemies collide with player bullets.
+    --
+    -- +-----------------+-----------------+---------------+
+    -- | Object          | Object Category | Category Mask |
+    -- +=================+=================+===============+
+    -- | \"Player\"      | 1               | 4, 5          |
+    -- +-----------------+-----------------+---------------+
+    -- | \"Enemy\"       | 2               | 2, 3, 5       |
+    -- +-----------------+-----------------+---------------+
+    -- | "Player Bullet" | 3               | 1, 5          |
+    -- +-----------------+-----------------+---------------+
+    -- | "Enemy Bullet"  | 4               | 2, 5          |
+    -- +-----------------+-----------------+---------------+
+    -- | \"Walls\"       | 5               | 1, 2, 3, 4    |
+    -- +-----------------+-----------------+---------------+
+    --
+    -- Note that everything in this example collides with walls. Additionally, the enemies collide with eachother.
+    --
+    -- By default, objects exist in every category and collide with every category.
+    --
+    -- Objects can fall into multiple categories. For instance, you might have a category for a red team,
+    -- and have a red player bullet. In the above example, each object only has one category.
+    --
+    -- There is one last way of filtering collisions using collision handlers. See the section on callbacks
+    -- for more information. Collision handlers can be more flexible, but can be slower.
+    -- Fast collision filtering rejects collisions before running the expensive collision detection code,
+    -- so using groups or category masks is preferred.
+
+    -- ** Memory Management Functions
+  , shapeFree
+
+    -- ** Misc functions
+  , shapeCacheBB
+  , shapeUpdate
+
+    -- ** Working With Circle Shapes
+  , circleShapeNew
+
+    -- ** Working With Segment Shapes
+  , segmentShapeNew
+  , segmentShapeNeighbors
+
+    -- ** Working With Polygon Shapes
+  , polyShapeNew
+  , polyShapeNewRaw
+
+    -- *** Boxes
+
+    -- | Because boxes are so common in physics games, Chipmunk provides shortcuts to create box shaped polygons.
+    -- The boxes will always be centered at the center of gravity of the body you are attaching them to.
+    -- Adding a small radius will bevel the corners and can significantly reduce problems
+    -- where the box gets stuck on seams in your geometry. If you want to create an off-center box,
+    -- you will need to use 'polyShapeNew'.
+  , boxShapeNew
+  , boxShapeNew2
+
+    -- *** Poly Shape Helper Functions
+  , centroidForPoly
+
+    -- *** Convex Hull Helper Functions
+  , convexHull
+
+    -- ** Modifying 'Shape's
+
+    -- | The short answer is that you can’t because the changes would be only picked up as a change to the position
+    -- of the shape’s surface, but not its velocity.
+
+    -- ** Notes
+
+    -- |
+    -- * You can attach multiple collision shapes to a rigid body. This should allow you to create almost any shape
+    -- you could possibly need.
+    --
+    -- * Shapes attached to the same rigid body will never generate collisions. You don’t have to worry
+    -- about overlap when attaching multiple shapes to a rigid body.
+    --
+    -- * Make sure you add both the body and its collision shapes to a space.
+
+    -- * Chipmunk Spaces
+  , Space
+
+    -- ** What Are Iterations, and Why Should I Care?
+
+    -- | Chipmunk uses an iterative solver to figure out the forces between objects in the space.
+    -- What this means is that it builds a big list of all of the collisions, joints, and other constraints
+    -- between the bodies and makes several passes over the list considering each one individually.
+    -- The number of passes it makes is the iteration count, and each iteration makes the solution more accurate.
+    -- If you use too many iterations, the physics should look nice and solid, but may use up too much CPU time.
+    -- If you use too few iterations, the simulation may seem mushy or bouncy when the objects should be solid.
+    -- Setting the number of iterations lets you balance between CPU usage and the accuracy of the physics.
+    -- Chipmunk’s default of 10 iterations is sufficient for most simple games.
+
+    -- ** Sleeping
+
+    -- | Spaces can disable entire groups of objects that have stopped moving to save CPU time and battery life.
+    -- In order to use this feature you must do two things. You must enable sleeping explicitly
+    -- by choosing a time threshold value with 'spaceSetSleepTimeThreshold'. This threshold is the amount of time
+    -- something must be idle before it falls asleep. 'spaceSetIdleSpeedThreshold' defines what is considered idle.
+    -- If you do not set idle speed threshold explicitly, a value will be chosen automatically
+    -- based on the current amount of gravity. Be mindful that objects cannot fall asleep if they are touching
+    -- or jointed to a kinematic body.
+
+    -- ** Properties
+
+  , spaceIterations
+  , spaceGravity
+  , spaceDamping
+  , spaceIdleSpeedThreshold
+  , spaceSleepTimeThreshold
+  , spaceCollisionSlop
+  , spaceCollisionBias
+  , spaceCollisionPersistence
+  , spaceCurrentTimeStep
+  , spaceIsLocked
+  , spaceUserData
+  , spaceStaticBody
+
+    -- ** Memory Management Functions
+
+    -- | More standard Chipmunk memory functions.
+  , spaceNew
+  , spaceFree
+
+    -- ** Operations
+
+    -- | These functions add and remove shapes, bodies and constraints from space. The add/remove functions
+    -- cannot be called from within a callback other than a 'postStep' callback (which is different than a 'postSolve'
+    -- callback!). Attempting to add or remove objects from the space while 'spaceStep' is still executing
+    -- will throw an assertion. See the callbacks section for more information. Be careful not to free bodies
+    -- before removing shapes and constraints attached to them or you will cause crashes..
+    -- The contains functions allow you to check if an object has been added to the space or not.
+  , spaceAddShape
+  , spaceAddBody
+  , spaceAddConstraint
+  , spaceRemoveShape
+  , spaceRemoveBody
+  , spaceRemoveConstraint
+  , spaceContainsShape
+  , spaceContainsBody
+  , spaceContainsConstraint
+
+    -- ** Spatial Indexing
+
+    -- | Occasionally, you might want to update the collision detection data for a shape.
+    -- If you move a static shape or a static body you must do this to let Chipmunk know
+    -- it needs to have its collision detection data updated. You may also want to manually update the collision data
+    -- for normal shapes if you move them and still want to perform queries against them
+    -- before the next call to 'spaceStep'.
+  , spaceReindexShape
+  , spaceReindexShapesForBody
+  , spaceReindexStatic
+
+    -- ** Iterators
+  , SpaceBodyIteratorFunc
+  , spaceEachBody
+  , SpaceShapeIteratorFunc
+  , spaceEachShape
+  , SpaceConstraintIteratorFunc
+  , spaceEachConstraint
+
+    -- ** Simulating the Space
+  , spaceStep
+
+    -- * Notes
+
+    -- |
+    -- * When removing objects from the space, make sure you remove any other objects that reference it.
+    -- For instance, when you remove a body, remove the joints and shapes attached to it.
+    --
+    -- * Using more iterations or smaller time steps will increase the physics quality, but also increase the CPU usage.
+
+    -- * Chipmunk Constraints
+  , Constraint
+
+    -- ** What constraints are and what they are not
+
+    -- | Constraints in Chipmunk are all velocity based constraints.
+    -- This means that they act primarily by synchronizing the velocity of two bodies.
+    -- A pivot joint holds two anchor points on two separate bodies together by defining equations that say
+    -- that the velocity of the anchor points must be the same and calculating impulses to apply to the bodies
+    -- to try and keep it that way. A constraint takes a velocity as it’s primary input and produces a velocity change
+    -- as its output. Some constraints, (joints in particular) apply velocity changes to correct differences
+    -- in positions. More about this in the next section.
+    --
+    -- A spring connected between two bodies is not a constraint. It’s very constraint-like as it creates forces
+    -- that affect the velocities of the two bodies, but a spring takes distances as input and produces forces
+    -- as its output. If a spring is not a constraint, then why do I have two varieties of spring constraints you ask?
+    -- The reason is because they are damped springs. The damping associated with the spring is a true constraint
+    -- that creates velocity changes based on the relative velocities of the two bodies it links.
+    -- As it is convenient to put a damper and a spring together most of the time, I figured I might as well just apply
+    -- the spring force as part of the constraint instead of having a damper constraint and having the user
+    -- calculate and apply their own spring forces separately.
+
+    -- ** Properties
+
+  , constraintBodyA
+  , constraintBodyB
+  , constraintMaxForce
+  , constraintErrorBias
+  , constraintMaxBias
+  , constraintSpace
+  , constraintCollideBodies
+  , constraintUserData
+  , constraintImpulse
+
+    -- ** Error correction by Feedback
+
+    -- | Joints in Chipmunk are not perfect. A pin joint can’t maintain the exact correct distance between its anchor
+    -- points, nor can a pivot joint hold its anchor points completely together. Instead, they are designed
+    -- to deal with this by correcting themselves over time. Since Chipmunk 5, you have a fair amount of extra control
+    -- over how joints correct themselves and can even use this ability to create physical effects
+    -- that allow you to use joints in unique ways:
+    --
+    -- * Servo motors – Ex: open/close doors or rotate things without going over a maximum force.
+    --
+    -- * Winches – Pull one object towards another at a constant speed without going over a maximum force.
+    --
+    -- * Mouse manipulation – Interact with objects smoothly given coarse/shaky mouse input.
+    --
+    -- There are three properties of 'Constraint' structs that control the error correction,
+    -- maxForce, maxBias, and biasCoef. maxForce is pretty self explanatory, a joint or constraint
+    -- will not be able to use more than this amount of force in order to function. If it needs more force
+    -- to be able to hold itself together, it will fall apart. maxBias is the maximum speed at which error correction
+    -- can be applied. If you change a property on a joint so that the joint will have to correct itself,
+    -- it normally does so very quickly. By setting a maxSpeed you can make the joint work like a servo,
+    -- correcting itself at a constant rate over a longer period of time. Lastly, biasCoef is the percentage
+    -- of error corrected every step before clamping to a maximum speed. You can use this
+    -- to make joints correct themselves smoothly instead of at a constant speed, but is probably the least useful
+    -- of the three properties by far.
+
+    -- ** Constraints and Collision Shapes
+
+    -- | Neither constraints or collision shapes have any knowledge of the other.
+    -- When connecting joints to a body the anchor points don’t need to be inside of any shapes attached to the body
+    -- and it often makes sense that they shouldn’t. Also, adding a constraint between two bodies
+    -- doesn’t prevent their collision shapes from colliding. In fact, this is the primary reason
+    -- that the collision group property exists.
+
+    -- ** Video Tour of Current Joint Types
+
+    -- | http://www.youtube.com/watch?v=ZgJJZTS0aMM
+
+    -- ** Shared Memory Management Functions
+  , constraintFree
+
+    -- ** Constraint Types
+
+    -- *** Pin Joints
+  , pinJointNew
+
+    -- **** Properties
+  , pinJointAnchorA
+  , pinJointAnchorB
+  , pinJointDist
+
+    -- *** Slide Joints
+  , slideJointNew
+
+    -- **** Properties
+  , slideJointAnchorA
+  , slideJointAnchorB
+  , slideJointMin
+  , slideJointMax
+
+    -- *** Pivot Joints
+
+    -- | (__Note for bindings__: So each instance of pivot joint can be replaced with pin joint with dist of 0?)
+
+  , pivotJointNew
+  , pivotJointNew2
+
+    -- **** Properties
+  , pivotJointAnchorA
+  , pivotJointAnchorB
+
+    -- *** Groove Joint
+  , grooveJointNew
+
+    -- **** Properties
+  , grooveJointGrooveA
+  , grooveJointGrooveB
+  , grooveJointAnchorB
+
+    -- *** Damped Spring
+  , dampedSpringNew
+
+    -- **** Properties
+  , dampedSpringAnchorA
+  , dampedSpringAnchorB
+  , dampedSpringRestLength
+  , dampedSpringStiffness
+  , dampedSpringDamping
+
+    -- *** Damped Rotary Spring
+
+    -- | Like a damped spring, but works in an angular fashion.
+  , dampedRotarySpringNew
+
+    -- **** Properties
+  , dampedRotarySpringRestAngle
+  , dampedRotarySpringStiffness
+  , dampedRotarySpringDamping
+
+    -- *** Rotary Limit Joint
+
+    -- | Constrains the relative rotations of two bodies.
+    -- It is implemented so that it’s possible to for the range to be greater than a full revolution.
+  , rotaryLimitJointNew
+
+    -- **** Properties
+  , rotaryLimitJointMin
+  , rotaryLimitJointMax
+
+    -- *** Ratchet Joint
+
+    -- | Works like a socket wrench.
+  , ratchetJointNew
+
+    -- **** Properties
+  , ratchetJointAngle
+  , ratchetJointPhase
+  , ratchetJointRatchet
+
+    -- *** Gear Joint
+
+    -- | Keeps the angular velocity ratio of a pair of bodies constant.
+  , gearJointNew
+
+    -- **** Properties
+  , gearJointPhase
+  , gearJointRatio
+
+    -- *** Simple Motor
+
+    -- | Keeps the relative angular velocity of a pair of bodies constant.
+    -- You will usually want to set an force (torque) maximum for motors as otherwise
+    -- they will be able to apply a nearly infinite torque to keep the bodies moving.
+  , simpleMotorNew
+
+    -- **** Properties
+  , simpleMotorRate
+
+    -- ** Notes
+
+    -- | * You can add multiple joints between two bodies, but make sure that they don’t fight.
+    -- Doing so can cause the bodies jitter or spin violently.
+
+    -- * Overview of Collision Detection in Chipmunk
+
+    -- | In order to make collision detection in Chipmunk as fast as possible, the process is broken down
+    -- into several stages. While I’ve tried to keep it conceptually simple, the implementation can be a bit daunting.
+    -- Fortunately as a user of the library, you don’t need to understand everything about how it works.
+    -- Though if you are trying to squeeze every bit of performance out of Chipmunk, understanding this section
+    -- can be helpful.
+
+    -- ** Spatial Indexing
+
+    -- | A for loop that checks every object against every other object in the scene would be very slow.
+    -- So the first stage of the collision detection, commonly called the broadphase, uses a high level
+    -- spatial algorithm to decide which pairs of objects to check for collisions.
+    -- Currently Chipmunk supports two spatial indexes, an axis-aligned bounding box tree and a spatial hash.
+    -- These spatial indexes are able to quickly identify which pairs of shapes are near each other
+    -- and should be checked for a collision.
+
+    -- ** Fast Collision Filtering
+
+    -- | After the spatial index figures out which pairs of shapes are likely to be near each other,
+    -- it passes each pair back to the space using a callback to perform some additional filtering on the pairs.
+    -- Before doing anything else, Chipmunk performs a few quick tests to check if shapes should collide.
+    --
+    -- * __Bounding Box Test__: The shapes are not colliding if their bounding boxes are not overlapping.
+    -- Objects like diagonal line segments can trigger a lot of false positives here,
+    -- but it’s unlikely to be something you should worry about.
+    --
+    -- * __Category Mask Test__: The categories of each shape are bitwise ANDed against the category mask
+    -- of the other shape. If either result is 0, the shapes do not collide.
+    --
+    -- * __Group Test__: Shapes shouldn’t collide with other shapes in the same non-zero group.
+
+    -- ** Constraint Based Filtering
+
+    -- | After fast collision filtering, Chipmunk checks the list of joints on one of the bodies
+    -- to see if it has a constraint that attaches it to the other body. If that constraint’s collideBodies
+    -- property is false, the collision will be ignored. This check is often very fast
+    -- since most scenes don’t contain a lot of constraints.
+
+    -- ** Primitive Shape to Shape Collision Detection
+
+    -- | The most expensive test is to actually check for overlap based on their geometry.
+    -- Circle to circle and circle to line collisions are very fast. Segment to segment and poly to poly collisions
+    -- are handled using the GJK/EPA algorithms, and get more expensive as the number of vertexes increases.
+    -- Simpler shapes make for faster collisions, and often more important, fewer collision points
+    -- for the solver to run. Chipmunk uses a small dispatch table to figure out which function to use to check
+    -- if the shapes overlap.
+    --
+    -- Without going into too much detail, the GJK algorithm checks the distance between two objects,
+    -- and the EPA algorithm checks how much they are overlapping. If you give you segment and poly shapes
+    -- a small radius when creating them, the EPA algorithm can usually be skipped, speeding up the collision detection
+    -- considerably. The radius should be at least as big as the amount of allowed collision slop.
+
+    -- ** Collision Handler Filtering
+
+    -- | After checking if two shapes overlap Chipmunk will look to see if you have defined a collision handler
+    -- for the collision types of the shapes. This is vital to process collisions events for the gameplay,
+    -- but also gives you a very flexible way to filter out collisions. The return value of the begin and preSolve
+    -- callbacks determines whether or not the colliding pair of shapes is discarded or not.
+    -- Returning true will keep the pair, false will discard it. Rejecting a collision from a begin callback
+    -- is permanent, rejecting it from the preSolve only applies to the step it occured in. If you don’t define
+    -- a handler for the given collision types, Chipmunk will call the space’s default handler, which by default
+    -- is defined to simply accept all collisions.
+    --
+    -- Wildcard collisions can also return a value, but they are handled in a more complicated way.
+    -- When you create a collision handler between two specific collision types, it’s your responsibility
+    -- to decide when to call the wildcard handlers and what to do with their return values.
+    -- Otherwise, the default is to call the wildcard handler for the first type, then the second type,
+    -- and use a logical AND of their return values as filtering value. See DefaultBegin() in cpSpace.c
+    -- for more information.
+    --
+    -- While using callbacks to filter collisions is the most flexible way, keep in mind that by the time your callback
+    -- is called all of the most expensive collision detection has already been done. For simulations
+    -- with a lot of colliding objects each frame, the time spent finding collisions is small compared to the time
+    -- spent solving the physics for them so it may not be a big deal. Fast collision filtering should be preferred
+    -- if possible.
+
+    -- * Collision Callbacks
+
+    -- | A physics library without any events or feedback would not be very useful for games.
+    -- How would you know when the player bumped into an enemy so that you could take some health points away?
+    -- How would you know how hard the car hit something so you don’t play a loud crash noise when a pebble hits it?
+    -- What if you need to decide if a collision should be ignored based on specific conditions,
+    -- like implementing one way platforms? Chipmunk has a number of powerful callback systems
+    -- that you can use to solve these problems.
+
+    -- ** Collision Handlers
+
+    -- | Collision handler function types. While all of them take an arbiter, space, and a user data pointer,
+    -- only the begin and preSolve callbacks return a value. See above for more information.
+  , CollisionCallback
+    -- Collision callbacks are closely associated with 'Arbiter' structs.
+    -- You should familiarize yourself with those as well.
+    --
+    -- __Note__: Shapes tagged as sensors (cpShape.sensor == true) never generate collisions that get processed,
+    -- so collisions between sensors shapes and other shapes will never call the postSolve callback.
+    -- They still generate begin, and separate callbacks, and the preSolve callback is also called
+    -- every frame even though there is no collision response.
+    --
+    -- __Note #2__: preSolve callbacks are called before the sleeping algorithm runs.
+    -- If an object falls asleep, its postSolve callback won’t be called until it’s reawoken.
+
+  , CollisionType
+  , CollisionHandler (..)
+  , CollisionHandlerPtr
+  , spaceAddCollisionHandler
+  , spaceAddWildcardHandler
+  , spaceAddDefaultCollisionHandler
+  , modifyCollisionHandler
+  , mkCallback
+  , mkCallbackB
+
+    -- ** Post-Step Callbacks
+
+    -- | Post-step callbacks are the one place where you can break the rules about adding or removing objects
+    -- from within a callback. In fact, their primary function is to help you safely remove objects from the space
+    -- that you wanted to disable or destroy in a collision or query callback.
+    --
+    -- Post step callbacks are registered as a function and a pointer that is used as a key.
+    -- You can only register one postStep callback per key. This prevents you from accidentally removing
+    -- an object more than once. For instance, say that you get a collision callback between a bullet and object A.
+    -- You want to destroy both the bullet and object A, so you register a postStep callback
+    -- to safely remove them from your game. Then you get a second collision callback between the bullet and object B.
+    -- You register a postStep callback to remove object B, and a second postStep callback to remove the bullet.
+    -- Because you can only register one callback per key, the postStep callback for the bullet
+    -- will only be called once and you can’t accidentally try to remove it twice.
+  , PostStepFunc
+  , spaceAddPostStepCallback
+
+    -- ** Examples
+
+    -- | See
+    -- <https://chipmunk-physics.net/release/ChipmunkLatest-Docs/examples.html#CollisionCallbacks the callback examples>
+    -- for more information.
+
+    -- * Chipmunk Collision Pairs
+  , Arbiter
+
+    -- ** Memory Management
+
+    -- | You will never need to create or free an arbiter. More importantly,
+    -- because they are entirely managed by the space you should never store a reference to an arbiter
+    -- as you don’t know when they will be freed or reused. Use them within the callback where they are given to you
+    -- and then forget about them or copy out the information you need.
+
+    -- ** Properties
+
+  , arbiterRestitution
+  , arbiterFriction
+  , arbiterSurfaceVelocity
+  , arbiterUserData
+
+    -- *** Collision Point(s)
+  , arbiterCount
+  , arbiterNormal
+  , arbiterPointA
+  , arbiterPointB
+  , arbiterDepth
+
+    -- *** Other
+  , arbiterIsFirstContact
+  , arbiterIsRemoval
+
+    -- *** Bodies and shapes
+  , arbiterShapes
+  , arbiterBodies
+
+    -- *** Running wildcard handlers
+
+    -- | These functions invoke the wildcard handlers for a given collision. For custom collision handlers
+    -- between specific types or overriding the default handler, you must decide how to invoke the wildcard handlers
+    -- since it may be important to call the wildcards first, last, or possibly skip them entirely.
+    -- For the begin and preSolve callbacks, you also need to decide what to do with their return values
+    -- since they may not agree with each other or the specific handler they were called from.
+    -- Every collision handler is defined for two types, the “A” variants of these functions call the wildcard handler
+    -- for the first type, and the “B” variants call the handler for the second type.
+
+  , arbiterCallWildcardBeginA
+  , arbiterCallWildcardBeginB
+  , arbiterCallWildcardPreSolveA
+  , arbiterCallWildcardPreSolveB
+  , arbiterCallWildcardPostSolveA
+  , arbiterCallWildcardPostSolveB
+  , arbiterCallWildcardSeparateA
+  , arbiterCallWildcardSeparateB
+
+    -- * Misc
+  , DataPtr
+  , Transform (..)
+
+    -- * Re-exports
+  , nullPtr
+  , HasGetter (..)
+  , HasSetter (..)
+  ) where
+
+import Foreign
+import Data.StateVar
+
+import Chiphunk.Low.Types
+import Chiphunk.Low.Math
+import Chiphunk.Low.Helper
+import Chiphunk.Low.Vect
+import Chiphunk.Low.BB
+import Chiphunk.Low.Body
+import Chiphunk.Low.Shape
+import Chiphunk.Low.Space
+import Chiphunk.Low.Constraint
+import Chiphunk.Low.Callback
+import Chiphunk.Low.Arbiter
diff --git a/src/Chiphunk/Low/Arbiter.chs b/src/Chiphunk/Low/Arbiter.chs
new file mode 100644
--- /dev/null
+++ b/src/Chiphunk/Low/Arbiter.chs
@@ -0,0 +1,172 @@
+module Chiphunk.Low.Arbiter
+  ( Arbiter
+  , arbiterRestitution
+  , arbiterFriction
+  , arbiterSurfaceVelocity
+  , arbiterUserData
+  , arbiterCount
+  , arbiterNormal
+  , arbiterPointA
+  , arbiterPointB
+  , arbiterDepth
+  , arbiterIsFirstContact
+  , arbiterIsRemoval
+  , arbiterShapes
+  , arbiterBodies
+  , arbiterCallWildcardBeginA
+  , arbiterCallWildcardBeginB
+  , arbiterCallWildcardPreSolveA
+  , arbiterCallWildcardPreSolveB
+  , arbiterCallWildcardPostSolveA
+  , arbiterCallWildcardPostSolveB
+  , arbiterCallWildcardSeparateA
+  , arbiterCallWildcardSeparateB
+  ) where
+
+import Data.StateVar
+import Foreign
+
+{# import Chiphunk.Low.Types #}
+
+#include <chipmunk/chipmunk.h>
+#include <wrapper.h>
+
+{# fun unsafe cpArbiterGetRestitution {`Arbiter'} -> `Double' #}
+
+{# fun unsafe cpArbiterSetRestitution {`Arbiter', `Double'} -> `()' #}
+
+-- | The calculated elasticity for this collision pair.
+-- Setting the value in a preSolve() callback will override the value calculated by the space.
+-- The default calculation multiplies the elasticity of the two shapes together.
+arbiterRestitution :: Arbiter -> StateVar Double
+arbiterRestitution = mkStateVar cpArbiterGetRestitution cpArbiterSetRestitution
+
+{# fun unsafe cpArbiterGetFriction {`Arbiter'} -> `Double' #}
+
+{# fun unsafe cpArbiterSetFriction {`Arbiter', `Double'} -> `()' #}
+
+-- | The calculated friction for this collision pair.
+-- Setting the value in a preSolve() callback will override the value calculated by the space.
+-- The default calculation multiplies the friction of the two shapes together.
+arbiterFriction :: Arbiter -> StateVar Double
+arbiterFriction = mkStateVar cpArbiterGetFriction cpArbiterSetFriction
+
+{# fun unsafe w_cpArbiterGetSurfaceVelocity {`Arbiter', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpArbiterSetSurfaceVelocity {`Arbiter', with* %`Vect'} -> `()' #}
+
+-- | The calculated surface velocity for this collision pair.
+-- Setting the value in a preSolve() callback will override the value calculated by the space.
+-- The default calculation subtracts the surface velocity of the second shape
+-- from the first and then projects that onto the tangent of the collision.
+-- This is so that only friction is affected by default calculation.
+--
+-- Using a custom calculation, you can make something that responds like a pinball bumper,
+-- or where the surface velocity is dependent on the location of the contact point.
+arbiterSurfaceVelocity :: Arbiter -> StateVar Vect
+arbiterSurfaceVelocity = mkStateVar w_cpArbiterGetSurfaceVelocity cpArbiterSetSurfaceVelocity
+
+{# fun unsafe cpArbiterGetUserData {`Arbiter'} -> `DataPtr' #}
+
+{# fun unsafe cpArbiterSetUserData {`Arbiter', `DataPtr'} -> `()' #}
+
+-- | A user definable context pointer.
+-- The value will persist until just after the separate callback is called for the pair.
+--
+-- __Note__: If you need to clean up this pointer, you should implement the separate callback to do it.
+-- Also be careful when destroying the space as there may be active collisions still.
+-- In order to trigger the separate callbacks and clean up your data,
+-- you’ll need to remove all the shapes from the space before disposing of it.
+-- This is something I’d suggest doing anyway.
+-- See ChipmunkDemo.c:ChipmunkDemoFreeSpaceChildren() for an example of how to do it easily.
+arbiterUserData :: Arbiter -> StateVar DataPtr
+arbiterUserData = mkStateVar cpArbiterGetUserData cpArbiterSetUserData
+
+{# fun unsafe cpArbiterGetCount {`Arbiter'} -> `Int' #}
+
+-- | The number of contacts tracked by this arbiter.
+-- For the forseeable future, the maximum number of contacts will be two.
+arbiterCount :: Arbiter -> GettableStateVar Int
+arbiterCount = makeGettableStateVar . cpArbiterGetCount
+
+{# fun unsafe w_cpArbiterGetNormal {`Arbiter', alloca- `Vect' peek*} -> `()' #}
+
+-- | Collision normal in a specific point tracked by this collision.
+arbiterNormal :: Arbiter -> GettableStateVar Vect
+arbiterNormal = makeGettableStateVar . w_cpArbiterGetNormal
+
+{# fun unsafe w_cpArbiterGetPointA {`Arbiter', `Int', alloca- `Vect' peek*} -> `()' #}
+
+-- | Collision point of a specific point on first body.
+arbiterPointA :: Arbiter -> Int -> GettableStateVar Vect
+arbiterPointA arbiter = makeGettableStateVar . w_cpArbiterGetPointA arbiter
+
+{# fun unsafe w_cpArbiterGetPointB {`Arbiter', `Int', alloca- `Vect' peek*} -> `()' #}
+
+-- | Collision point of a specific point on second body.
+arbiterPointB :: Arbiter -> Int -> GettableStateVar Vect
+arbiterPointB arbiter = makeGettableStateVar . w_cpArbiterGetPointB arbiter
+
+{# fun unsafe cpArbiterGetDepth {`Arbiter', `Int'} -> `Double' #}
+
+-- | Penetration depth of a collision point.
+arbiterDepth :: Arbiter -> Int -> GettableStateVar Double
+arbiterDepth arbiter = makeGettableStateVar . cpArbiterGetDepth arbiter
+
+-- | Returns true if this is the first step the two shapes started touching. This can be useful for sound effects
+-- for instance. If its the first frame for a certain collision, check the energy of the collision in a postStep
+-- callbock and use that to determine the volume of a sound effect to play.
+{# fun unsafe cpArbiterIsFirstContact as arbiterIsFirstContact {`Arbiter'} -> `Bool' #}
+
+-- | Returns 'True' during a separate callback if the callback was invoked due to an object removal.
+{# fun unsafe cpArbiterIsRemoval as arbiterIsRemoval {`Arbiter'} -> `Bool' #}
+
+{# fun unsafe cpArbiterGetShapes
+  { `Arbiter'
+  , alloca- `Shape' peek*
+  , alloca- `Shape' peek*
+  } -> `()' #}
+
+-- | The colliding shapes in the order that they were defined in the collision handler
+-- associated with this arbiter.
+-- If you defined the handler as cpSpaceAddCollisionHandler(space, 1, 2, ...),
+-- you you will find that a->collision_type == 1 and b->collision_type == 2.
+arbiterShapes :: Arbiter -> GettableStateVar (Shape, Shape)
+arbiterShapes = makeGettableStateVar . cpArbiterGetShapes
+
+{# fun unsafe cpArbiterGetBodies
+  { `Arbiter'
+  , alloca- `Body' peek*
+  , alloca- `Body' peek*
+  } -> `()' #}
+
+-- | The colliding bodies in the order that they were defined in the collision handler
+-- associated with this arbiter.
+-- If you defined the handler as cpSpaceAddCollisionHandler(space, 1, 2, ...),
+-- you you will find that a->collision_type == 1 and b->collision_type == 2.
+arbiterBodies :: Arbiter -> GettableStateVar (Body, Body)
+arbiterBodies = makeGettableStateVar . cpArbiterGetBodies
+
+-- | Run begin wildcard callback for first body.
+{# fun cpArbiterCallWildcardBeginA as arbiterCallWildcardBeginA {`Arbiter', `Space'} -> `Bool' #}
+
+-- | Run begin wildcard callback for second body.
+{# fun cpArbiterCallWildcardBeginB as arbiterCallWildcardBeginB {`Arbiter', `Space'} -> `Bool' #}
+
+-- | Run preSolve wildcard callback for first body.
+{# fun cpArbiterCallWildcardPreSolveA as arbiterCallWildcardPreSolveA {`Arbiter', `Space'} -> `Bool' #}
+
+-- | Run preSolve wildcard callback for second body.
+{# fun cpArbiterCallWildcardPreSolveB as arbiterCallWildcardPreSolveB {`Arbiter', `Space'} -> `Bool' #}
+
+-- | Run postSolve wildcard callback for first body.
+{# fun cpArbiterCallWildcardPostSolveA as arbiterCallWildcardPostSolveA {`Arbiter', `Space'} -> `()' #}
+
+-- | Run postSolve wildcard callback for second body.
+{# fun cpArbiterCallWildcardPostSolveB as arbiterCallWildcardPostSolveB {`Arbiter', `Space'} -> `()' #}
+
+-- | Run separate wildcard callback for first body.
+{# fun cpArbiterCallWildcardSeparateA as arbiterCallWildcardSeparateA {`Arbiter', `Space'} -> `()' #}
+
+-- | Run separate wildcard callback for second body.
+{# fun cpArbiterCallWildcardSeparateB as arbiterCallWildcardSeparateB {`Arbiter', `Space'} -> `()' #}
diff --git a/src/Chiphunk/Low/BB.chs b/src/Chiphunk/Low/BB.chs
new file mode 100644
--- /dev/null
+++ b/src/Chiphunk/Low/BB.chs
@@ -0,0 +1,128 @@
+-- | Description: Utilities for working with bounding box.
+-- Module provides utilities for working with bounding box.
+module Chiphunk.Low.BB
+  ( BB (..)
+  , bbNew
+  , bbNewForExtents
+  , bbNewForCircle
+  , bbIntersects
+  , bbContainsBB
+  , bbContainsVect
+  , bbMerge
+  , bbExpand
+  , bbCenter
+  , bbArea
+  , bbMergedArea
+  , bbSegmentQuery
+  , bbIntersectsSegment
+  , bbClampVect
+  , bbWrapVect
+  ) where
+
+import Data.Fixed
+import Foreign
+
+import Chiphunk.Low.Math
+
+{# import Chiphunk.Low.Types #}
+
+#include <chipmunk/chipmunk.h>
+#include <wrapper.h>
+
+-- | Convenience constructor for 'BB' structs.
+bbNew :: Double -> Double -> Double -> Double -> BB
+bbNew = BB
+
+-- | Convenience constructor for making a 'BB' fitting with a center point and half width and height.
+bbNewForExtents
+  :: Vect   -- ^ Center point
+  -> Double -- ^ Half width
+  -> Double -- ^ Half height
+  -> BB
+bbNewForExtents (Vect x y) hw hh = BB (x - hw) (y - hh) (x + hw) (y + hh)
+
+-- | Convenience constructor for making a 'BB' fitting a circle at position @p@ with radius @r@.
+bbNewForCircle
+  :: Vect   -- ^ p
+  -> Double -- ^ r
+  -> BB
+bbNewForCircle v r = bbNewForExtents v r r
+
+-- | Returns true if the bounding boxes intersect.
+bbIntersects :: BB -> BB -> Bool
+BB l1 b1 r1 t1 `bbIntersects` BB l2 b2 r2 t2 = r1 >= l1 && r2 >= l2 && t1 >= b1 && t2 >= b2
+
+-- | Returns true if @bb@ completely contains @other@.
+bbContainsBB
+  :: BB   -- ^ bb
+  -> BB   -- ^ other
+  -> Bool
+BB l1 b1 r1 t1 `bbContainsBB` BB l2 b2 r2 t2 = l1 <= l2 && r1 >= r2 && t1 >= t2 && b1 <= b2
+
+-- | Returns true if @bb@ contains @v@.
+bbContainsVect
+  :: BB   -- ^ bb
+  -> Vect -- ^ v
+  -> Bool
+BB l b r t `bbContainsVect` Vect x y = l <= x && r >= x && b <= y && t >= y
+
+-- | Return the minimal bounding box that contains both @a@ and @b@.
+bbMerge
+  :: BB -- ^ a
+  -> BB -- ^ b
+  -> BB
+BB l1 b1 r1 t1 `bbMerge` BB l2 b2 r2 t2 = BB (min l1 l2) (min b1 b2) (max r1 r2) (max t1 t2)
+
+-- | Return the minimal bounding box that contains both @bb@ and @v@.
+bbExpand
+  :: BB   -- ^ bb
+  -> Vect -- ^ v
+  -> BB
+BB l b r t `bbExpand` Vect x y = BB (min l x) (min b y) (max r x) (max t y)
+
+-- | Return the center of @bb@.
+bbCenter
+  :: BB   -- ^ bb
+  -> Vect
+bbCenter (BB l b r t) = Vect ((l + r) / 2) ((b + t) / 2)
+
+-- | Return the area of @bb@.
+bbArea
+  :: BB     -- ^ bb
+  -> Double
+bbArea (BB l b r t) = (r - l) * (t - b)
+
+-- | Merges @a@ and @b@ then returns the area of the merged bounding box.
+bbMergedArea
+  :: BB     -- ^ a
+  -> BB     -- ^ b
+  -> Double
+BB l1 b1 r1 t1 `bbMergedArea` BB l2 b2 r2 t2 = (max r1 r2 - min l1 l2) * (max t1 t2 - min b1 b2)
+
+-- | Returns the fraction along the segment query the 'BB' is hit. Returns INFINITY if it doesn’t hit.
+{# fun pure unsafe w_cpBBSegmentQuery as bbSegmentQuery
+  { with* %`BB'   -- ^ Box
+  , with* %`Vect' -- ^ One segment end
+  , with* %`Vect' -- ^ Other segment end
+  } -> `Double' #}
+
+-- | Returns true if the segment defined by endpoints @a@ and @b@ intersect @bb@.
+{# fun pure unsafe w_cpBBIntersectsSegment as bbIntersectsSegment
+  { with* %`BB'   -- ^ bb
+  , with* %`Vect' -- ^ a
+  , with* %`Vect' -- ^ b
+  } -> `Bool' #}
+
+-- | Returns a copy of @v@ clamped to the bounding box @bb@.
+bbClampVect
+  :: BB   -- ^ bb
+  -> Vect -- ^ v
+  -> Vect
+BB l b r t `bbClampVect` Vect x y = Vect (fClamp x l r) (fClamp y b t)
+
+-- | Returns a copy of @v@ wrapped to the bounding box @bb@.
+bbWrapVect
+  :: BB   -- ^ bb
+  -> Vect -- ^ v
+  -> Vect
+BB l b r t `bbWrapVect` Vect x y = Vect (l + ((x - l) `mod'` abs (r - l))) (b + ((y - b) `mod'` abs (t - b)))
diff --git a/src/Chiphunk/Low/Body.chs b/src/Chiphunk/Low/Body.chs
new file mode 100644
--- /dev/null
+++ b/src/Chiphunk/Low/Body.chs
@@ -0,0 +1,319 @@
+-- | Description: Rigid bodies manipulations
+-- Module provides access to the rigid bodies which are at the core of the physics simulation.
+module Chiphunk.Low.Body
+  ( Body
+  , BodyType (..)
+  , bodyNew
+  , bodyNewKinematic
+  , bodyNewStatic
+  , bodyFree
+  , bodyType
+  , bodyMass
+  , bodyMoment
+  , bodyPosition
+  , bodyCenterOfGravity
+  , bodyVelocity
+  , bodyForce
+  , bodyAngle
+  , bodyAngularVelocity
+  , bodyTorque
+  , bodyRotation
+  , bodySpace
+  , bodyUserData
+  , bodyLocalToWorld
+  , bodyWorldToLocal
+  , bodyVelocityAtWorldPoint
+  , bodyVelocityAtLocalPoint
+  , bodyApplyForceAtWorldPoint
+  , bodyApplyForceAtLocalPoint
+  , bodyApplyImpulseAtWorldPoint
+  , bodyApplyImpulseAtLocalPoint
+  , bodyIsSleeping
+  , bodyActivate
+  , bodySleep
+  , bodyActivateStatic
+  , bodySleepWithGroup
+  , BodyShapeIteratorFunc
+  , bodyEachShape
+  , BodyConstraintIteratorFunc
+  , bodyEachConstraint
+  , BodyArbiterIteratorFunc
+  , bodyEachArbiter
+  ) where
+
+import Chiphunk.Low.Vect
+import Control.Exception.Safe
+import Data.StateVar
+import Foreign
+
+{# import Chiphunk.Low.Types #}
+
+#include <chipmunk/chipmunk.h>
+#include <wrapper.h>
+
+-- | Creates body of type 'BodyTypeDynamic'.
+{# fun unsafe cpBodyNew as bodyNew
+  { `Double' -- ^ Mass of the body. Guessing is usually fine.
+
+  , `Double' -- ^ Moment of inertia of the body.
+             -- Guessing a moment of inertia can lead to a very poor simulation
+             -- so it’s recommended to use Chipmunk’s moment calculations
+             -- to estimate the moment for you.
+  } -> `Body' #}
+
+-- | Create body of type 'BodyTypeKimenatic'.
+{# fun unsafe cpBodyNewKinematic as bodyNewKinematic {} -> `Body' #}
+
+-- | Create body of type 'BodyTypeStatic'.
+{# fun unsafe cpBodyNewStatic as bodyNewStatic {} -> `Body' #}
+
+-- | Be careful not to free a body before any shapes or constraints attached to it
+-- have been removed from a space.
+{# fun cpBodyFree as bodyFree {`Body'} -> `()' #}
+-- no "unsafe" qualifier because I think it may trigger callbacks
+
+-- | Get the type of a body (dynamic, kinematic, static).
+{# fun unsafe cpBodyGetType {`Body'} -> `BodyType' #}
+
+{# fun unsafe cpBodySetType {`Body', `BodyType'} -> `()' #}
+
+-- | Type of a body (dynamic, kinematic, static).
+-- When changing an body to a dynamic body, the mass and moment of inertia
+-- are recalculated from the shapes added to the body.
+-- Custom calculated moments of inertia are not preseved when changing types.
+-- This function cannot be called directly in a collision callback.
+bodyType :: Body -> StateVar BodyType
+bodyType = mkStateVar cpBodyGetType cpBodySetType
+
+{# fun unsafe cpBodyGetMass {`Body'} -> `Double' #}
+
+{# fun unsafe cpBodySetMass {`Body', `Double'} -> `()' #}
+
+-- | Mass of the body.
+bodyMass :: Body -> StateVar Double
+bodyMass = mkStateVar cpBodyGetMass cpBodySetMass
+
+{# fun unsafe cpBodyGetMoment {`Body'} -> `Double' #}
+
+{# fun unsafe cpBodySetMoment {`Body', `Double'} -> `()' #}
+
+-- | Moment of inertia (MoI or sometimes just moment) of the body.
+-- The moment is like the rotational mass of a body.
+-- See below for function to help calculate the moment.
+bodyMoment :: Body -> StateVar Double
+bodyMoment = mkStateVar cpBodyGetMoment cpBodySetMoment
+
+{# fun unsafe w_cpBodyGetPosition {`Body', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpBodySetPosition {`Body', with* %`Vect'} -> `()' #}
+
+-- | Position of the body. When changing the position you may also want to call
+-- 'spaceReindexShapesForBody' to update the collision detection information
+-- for the attached shapes if plan to make any queries against the space.
+bodyPosition :: Body -> StateVar Vect
+bodyPosition = mkStateVar w_cpBodyGetPosition cpBodySetPosition
+
+{# fun unsafe w_cpBodyGetCenterOfGravity {`Body', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpBodySetCenterOfGravity {`Body', with* %`Vect'} -> `()' #}
+
+-- | Location of the center of gravity in body local coordinates.
+-- The default value is (0, 0), meaning the center of gravity
+-- is the same as the position of the body.
+bodyCenterOfGravity :: Body -> StateVar Vect
+bodyCenterOfGravity = mkStateVar w_cpBodyGetCenterOfGravity cpBodySetCenterOfGravity
+
+{# fun unsafe w_cpBodyGetVelocity {`Body', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpBodySetVelocity {`Body', with* %`Vect'} -> `()' #}
+
+-- | Linear velocity of the center of gravity of the body.
+bodyVelocity :: Body -> StateVar Vect
+bodyVelocity = mkStateVar w_cpBodyGetVelocity cpBodySetVelocity
+
+{# fun unsafe w_cpBodyGetForce {`Body', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpBodySetForce {`Body', with* %`Vect'} -> `()' #}
+
+-- | Force applied to the center of gravity of the body.
+-- This value is reset for every time step.
+bodyForce :: Body -> StateVar Vect
+bodyForce = mkStateVar w_cpBodyGetForce cpBodySetForce
+
+{# fun unsafe cpBodyGetAngle {`Body'} -> `Double' #}
+
+{# fun unsafe cpBodySetAngle {`Body', `Double'} -> `()' #}
+
+-- | Set rotation of the body in radians.
+-- When changing the rotation you may also want to call 'spaceReindexShapesForBody'
+-- to update the collision detection information for the attached shapes
+-- if you plan to make any queries against the space.
+-- A body rotates around its center of gravity, not its position.
+bodyAngle :: Body -> StateVar Double
+bodyAngle = mkStateVar cpBodyGetAngle cpBodySetAngle
+
+{# fun unsafe cpBodyGetAngularVelocity {`Body'} -> `Double' #}
+
+{# fun unsafe cpBodySetAngularVelocity {`Body', `Double'} -> `()' #}
+
+-- | Angular velocity of the body in radians per second.
+bodyAngularVelocity :: Body -> StateVar Double
+bodyAngularVelocity = mkStateVar cpBodyGetAngularVelocity cpBodySetAngularVelocity
+
+{# fun unsafe cpBodyGetTorque {`Body'} -> `Double' #}
+
+{# fun unsafe cpBodySetTorque {`Body', `Double'} -> `()' #}
+
+-- | Torque applied to the body. This value is reset for every time step.
+bodyTorque :: Body -> StateVar Double
+bodyTorque = mkStateVar cpBodyGetTorque cpBodySetTorque
+
+{# fun unsafe w_cpBodyGetRotation {`Body', alloca- `Vect' peek*} -> `()' #}
+
+-- | The rotation vector for the body.
+-- Can be used with 'vRotate' or 'vUnRotate' to perform fast rotations.
+bodyRotation :: Body -> GettableStateVar Vect
+bodyRotation = makeGettableStateVar . w_cpBodyGetRotation
+
+{# fun unsafe cpBodyGetSpace {`Body'} -> `Space' #}
+
+-- | The 'Space' that body has been added to.
+bodySpace :: Body -> GettableStateVar Space
+bodySpace = makeGettableStateVar . cpBodyGetSpace
+
+{# fun unsafe cpBodyGetUserData {`Body'} -> `DataPtr' #}
+
+{# fun unsafe cpBodySetUserData {`Body', `DataPtr'} -> `()' #}
+
+-- | User data pointer. Use this pointer to get a reference to the game object
+-- that owns this body from callbacks.
+bodyUserData :: Body -> StateVar DataPtr
+bodyUserData = mkStateVar cpBodyGetUserData cpBodySetUserData
+
+-- | Convert from body local coordinates to world space coordinates.
+{# fun unsafe w_cpBodyLocalToWorld as bodyLocalToWorld {`Body', with* %`Vect', alloca- `Vect' peek*} -> `()' #}
+
+-- | Convert from world space coordinates to body local coordinates.
+{# fun unsafe w_cpBodyWorldToLocal as bodyWorldToLocal {`Body', with* %`Vect', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe w_cpBodyGetVelocityAtWorldPoint
+  {`Body', with* %`Vect', alloca- `Vect' peek*} -> `()' #}
+
+-- | Absolute velocity of the rigid body at the given world point.
+bodyVelocityAtWorldPoint :: Body -> Vect -> GettableStateVar Vect
+bodyVelocityAtWorldPoint body = makeGettableStateVar . w_cpBodyGetVelocityAtWorldPoint body
+
+{# fun unsafe w_cpBodyGetVelocityAtLocalPoint
+  {`Body', with* %`Vect', alloca- `Vect' peek*} -> `()' #}
+
+-- | Absolute velocity of the rigid body at the given body local point.
+bodyVelocityAtLocalPoint :: Body -> Vect -> GettableStateVar Vect
+bodyVelocityAtLocalPoint body = makeGettableStateVar . w_cpBodyGetVelocityAtLocalPoint body
+
+-- | Add the @force@ to @body@ as if applied from the world @point@.
+{# fun unsafe cpBodyApplyForceAtWorldPoint as bodyApplyForceAtWorldPoint
+  { `Body'        -- ^ body
+  , with* %`Vect' -- ^ force
+  , with* %`Vect' -- ^ point
+  } -> `()' #}
+
+-- | Add the local @force@ to @body@ as if applied from the body local @point@.
+{# fun unsafe cpBodyApplyForceAtLocalPoint as bodyApplyForceAtLocalPoint
+  { `Body'        -- ^ body
+  , with* %`Vect' -- ^ force
+  , with* %`Vect' -- ^ point
+  } -> `()' #}
+
+-- | Add the @impulse@ to @body@ as if applied from the world @ point@.
+{# fun unsafe cpBodyApplyImpulseAtWorldPoint as bodyApplyImpulseAtWorldPoint
+  { `Body'        -- ^ body
+  , with* %`Vect' -- ^ impulse
+  , with* %`Vect' -- ^ point
+  } -> `()' #}
+
+-- | Add the local @impulse@ to @body@ as if applied from the body local @point@.
+{# fun unsafe cpBodyApplyImpulseAtLocalPoint as bodyApplyImpulseAtLocalPoint
+  { `Body'        -- ^ body
+  , with* %`Vect' -- ^ impulse
+  , with* %`Vect' -- ^ point
+  } -> `()' #}
+
+-- | Returns true if body is sleeping.
+{# fun unsafe cpBodyIsSleeping as bodyIsSleeping {`Body'} -> `Bool' #}
+
+-- | Reset the idle timer on a body. If it was sleeping, wake it and any other bodies it was touching.
+{# fun unsafe cpBodyActivate as bodyActivate {`Body'} -> `()' #}
+
+-- | Forces a body to fall asleep immediately even if it’s in midair. Cannot be called from a callback.
+{# fun unsafe cpBodySleep as bodySleep {`Body'} -> `()' #}
+
+-- | Activates all bodies touching @body@.
+-- If @filter@ is not 'nullPtr', then only bodies touching through @filter@ will be awoken.
+{# fun unsafe cpBodyActivateStatic as bodyActivateStatic
+  { `Body'  -- ^ body
+  , `Shape' -- ^ filter
+  } -> `()' #}
+
+-- | When objects in Chipmunk sleep, they sleep as a group of all objects that are touching or jointed together.
+-- When an object is woken up, all of the objects in its group are woken up.
+-- 'bodySleepWithGroup' allows you group sleeping objects together.
+-- It acts identically to 'bodySleep' if you pass 'nullPtr' as @group@ by starting a new group.
+-- If you pass a sleeping body for @group@, @body@ will be awoken when group is awoken.
+-- You can use this to initialize levels and start stacks of objects in a pre-sleeping state.
+{# fun unsafe cpBodySleepWithGroup as bodySleepWithGroup
+  { `Body' -- ^ body
+  , `Body' -- ^ group
+  } -> `()' #}
+
+-- | Type of callback which can be used to iterate all 'Shape's in a 'Body'.
+type BodyShapeIteratorFunc = Body -> Shape -> Ptr () -> IO ()
+
+foreign import ccall unsafe "wrapper"
+  mkBodyShapeIteratorFunc :: BodyShapeIteratorFunc -> IO (FunPtr BodyShapeIteratorFunc)
+
+-- | Call @func@ once for each shape that is attached to @body@ and added to a space.
+-- @data@ is passed along as a context value. It is safe to remove shapes using these callbacks.
+{# fun cpBodyEachShape as bodyEachShape
+  { `Body'                                -- ^ body
+  , withIterator* `BodyShapeIteratorFunc' -- ^ func
+  , `Ptr ()'                              -- ^ data
+  } -> `()' #}
+  where
+    withIterator i = mkBodyShapeIteratorFunc i `bracket` freeHaskellFunPtr
+
+-- | Type of callback which can be used to iterate all 'Constraint's in a 'Body'.
+type BodyConstraintIteratorFunc = Body -> Constraint -> Ptr () -> IO ()
+
+foreign import ccall unsafe "wrapper"
+  mkBodyConstraintIteratorFunc :: BodyConstraintIteratorFunc -> IO (FunPtr BodyConstraintIteratorFunc)
+
+-- | Call @func@ once for each constraint that is attached to @body@ and added to a space.
+-- @data@ is passed along as a context value. It is safe to remove constraints using thes callbacks.
+{# fun cpBodyEachConstraint as bodyEachConstraint
+  { `Body'                                     -- ^ body
+  , withIterator* `BodyConstraintIteratorFunc' -- ^ func
+  , `Ptr ()'                                   -- ^ data
+  } -> `()' #}
+  where
+    withIterator i = mkBodyConstraintIteratorFunc i `bracket` freeHaskellFunPtr
+
+-- | Type of callback which can be used to iterate all 'Arbiter's in a 'Body'.
+type BodyArbiterIteratorFunc = Body -> Arbiter -> Ptr () -> IO ()
+
+foreign import ccall unsafe "wrapper"
+  mkBodyArbiterIteratorFunc :: BodyArbiterIteratorFunc -> IO (FunPtr BodyArbiterIteratorFunc)
+
+-- | This one is more interesting. Calls @func@ once for each collision pair that @body@ is involved in.
+-- Calling 'arbiterGetBodies'/'arbiterGetShapes' will return the body or shape for body as the first argument.
+-- You can use this to check all sorts of collision information for a body like if it’s touching the ground,
+-- another particular object, how much collision force is being applied to an object, etc.
+--
+-- Sensor shapes and arbiters that have been rejected by a collision handler callback or 'arbiterIgnore'
+-- are not tracked by the contact graph.
+{# fun cpBodyEachArbiter as bodyEachArbiter
+  { `Body'                                  -- ^ body
+  , withIterator* `BodyArbiterIteratorFunc' -- ^ func
+  , `Ptr ()'                                -- ^ data
+  } -> `()' #}
+  where
+    withIterator i = mkBodyArbiterIteratorFunc i `bracket` freeHaskellFunPtr
diff --git a/src/Chiphunk/Low/Callback.chs b/src/Chiphunk/Low/Callback.chs
new file mode 100644
--- /dev/null
+++ b/src/Chiphunk/Low/Callback.chs
@@ -0,0 +1,159 @@
+-- | Description: Collision handler definition
+-- Module provides definitions for collision handlers.
+module Chiphunk.Low.Callback
+  ( CollisionCallback
+  , CollisionHandler (..)
+  , CollisionHandlerPtr
+  , spaceAddCollisionHandler
+  , spaceAddWildcardHandler
+  , spaceAddDefaultCollisionHandler
+  , modifyCollisionHandler
+  , mkCallback
+  , mkCallbackB
+  , PostStepFunc
+  , spaceAddPostStepCallback
+  ) where
+
+import Control.Applicative (liftA)
+import Control.Exception.Safe
+import Data.Bool (bool)
+import Foreign
+
+{# import Chiphunk.Low.Types #}
+
+#include <chipmunk/chipmunk.h>
+
+-- | Collision callback
+type CollisionCallback ret = Arbiter -> Space -> DataPtr -> IO ret
+
+-- | This collision handler processes collisions between objects of type @typeA@ and @typeB@.
+-- Fill the desired collision callback functions- they are documented above. A user definable context pointer
+-- @userData@ is included for your convenience. This pointer is provided as an argument in each callback function.
+--
+-- A collision handler is a set of 4 function callbacks for the different collision events that Chipmunk recognizes.
+data CollisionHandler = CollisionHandler
+  { chTypeA         :: !CollisionType                   -- ^ typeA
+  , chTypeB         :: !CollisionType                   -- ^ typeB
+  , chBeginFunc     :: !(FunPtr (CollisionCallback CPBool))
+    -- ^ Two shapes just started touching for the first time this step. Return true from the callback
+    -- to process the collision normally or false to cause Chipmunk to ignore the collision entirely.
+    -- If you return false, the preSolve and postSolve callbacks will never be run, but you will still recieve
+    -- a separate event when the shapes stop overlapping.
+  , chPreSolveFunc  :: !(FunPtr (CollisionCallback CPBool))
+    -- ^ Two shapes are touching during this step. Return false from the callback to make Chipmunk ignore the collision
+    -- this step or true to process it normally. Additionally, you may override collision values using
+    -- 'Chiphunk.Low.Arbiter.arbiterFriction', 'Chiphunk.Low.Arbiter.arbiterRestitution' or
+    -- 'Chiphunk.Low.arbiterSurfaceVelocity' to provide custom friction, elasticity, or surface velocity values.
+    -- See 'Arbiter' for more info.
+  , chPostSolveFunc :: !(FunPtr (CollisionCallback ()))
+    -- ^ Two shapes are touching and their collision response has been processed. You can retrieve the collision
+    -- impulse or kinetic energy at this time if you want to use it to calculate sound volumes or damage amounts.
+    -- See 'Arbiter' for more info.
+  , chSeparateFunc  :: !(FunPtr (CollisionCallback ()))
+    -- ^ Two shapes have just stopped touching for the first time this step. To ensure that begin/separate
+    -- are always called in balanced pairs, it will also be called when removing a shape while its in contact
+    -- with something or when deallocating the space.
+  , cpUserData      :: !DataPtr                         -- ^ userData
+  } deriving Show
+
+instance Storable CollisionHandler where
+  sizeOf _ = {# sizeof cpCollisionHandler #}
+  alignment _ = {# alignof cpCollisionHandler #}
+  poke p (CollisionHandler typA typB beginFunc preSolveFunc postSolveFunc separateFunc userData) = do
+    {# set cpCollisionHandler->typeA #} p $ fromIntegral typA
+    {# set cpCollisionHandler->typeB #} p $ fromIntegral typB
+    {# set cpCollisionHandler->beginFunc #} p beginFunc
+    {# set cpCollisionHandler->preSolveFunc #} p preSolveFunc
+    {# set cpCollisionHandler->postSolveFunc #} p postSolveFunc
+    {# set cpCollisionHandler->separateFunc #} p separateFunc
+    {# set cpCollisionHandler->userData #} p userData
+  peek p = CollisionHandler <$> (fromIntegral <$> {# get cpCollisionHandler->typeA #} p)
+                            <*> (fromIntegral <$> {# get cpCollisionHandler->typeB #} p)
+                            <*> {# get cpCollisionHandler->beginFunc #} p
+                            <*> {# get cpCollisionHandler->preSolveFunc #} p
+                            <*> {# get cpCollisionHandler->postSolveFunc #} p
+                            <*> {# get cpCollisionHandler->separateFunc #} p
+                            <*> {# get cpCollisionHandler->userData #} p
+
+foreign import ccall unsafe "wrapper"
+  mkCallback' :: CollisionCallback () -> IO (FunPtr (CollisionCallback ()))
+
+-- | Make callback. Need to free afterwards.
+mkCallback :: CollisionCallback () -> IO (FunPtr (CollisionCallback ()))
+mkCallback = mkCallback'
+
+foreign import ccall unsafe "wrapper"
+  mkCallbackB' :: CollisionCallback CPBool -> IO (FunPtr (CollisionCallback CPBool))
+
+-- | Make callback. Need to free afterwards.
+mkCallbackB :: CollisionCallback Bool -> IO (FunPtr (CollisionCallback CPBool))
+mkCallbackB = mkCallbackB' . liftA (liftA $ liftA $ liftA $ bool 0 1)
+
+-- | Pointer to collision handler
+{# pointer *cpCollisionHandler as CollisionHandlerPtr -> CollisionHandler #}
+
+-- | Add a 'CollisionHandler' for specific collision type pair or return the existing handler for the type pair.
+-- Whenever shapes with collision types (cpShape.collision_type) a and b collide,
+-- this handler will be used to process the collision events. When a new collision handler is created,
+-- the callbacks will all be set to builtin callbacks that perform the default behavior
+-- (call the wildcard handlers, and accept all collisions).
+{# fun unsafe cpSpaceAddCollisionHandler as spaceAddCollisionHandler
+  { `Space'
+  , fromIntegral `CollisionType' -- ^ a
+  , fromIntegral `CollisionType' -- ^ b
+  } -> `CollisionHandlerPtr' #}
+
+-- | Add a wildcard collision handler for given collision type. This handler will be used any time an object
+-- with this type collides with another object, regardless of its type. A good example is a projectile
+-- that should be destroyed the first time it hits anything. There may be a specific collision handler
+-- and two wildcard handlers. It’s up to the specific handler to decide if and when to call the wildcard handlers
+-- and what to do with their return values. (See arbiterCallWildcard* below)
+-- When a new wildcard handler is created, the callbacks will all be set to builtin callbacks
+-- that perform the default behavior. (accept all collisions in begin and preSolve, or do nothing for postSolve
+-- and separate.
+{# fun unsafe cpSpaceAddWildcardHandler as spaceAddWildcardHandler
+  { `Space'
+  , fromIntegral `CollisionType' -- ^ type
+  } -> `CollisionHandlerPtr' #}
+
+-- | Return a reference to the default collision handler or that is used to process all collisions
+-- that don’t have a more specific handler. The default behavior for each of the callbacks
+-- is to call the wildcard handlers, ANDing their return values together if applicable.
+{# fun unsafe cpSpaceAddDefaultCollisionHandler as spaceAddDefaultCollisionHandler
+  { `Space'
+  } -> `CollisionHandlerPtr' #}
+
+-- | Use this helper function to modify collision handler.
+--
+-- @
+-- spaceAddCollisionHandler s t1 t2 >>= flip modifyColliionHandler (\ch -> pure ch {chSeparateFunc = separateCollback})
+-- @
+modifyCollisionHandler :: CollisionHandlerPtr -> (CollisionHandler -> IO CollisionHandler) -> IO ()
+modifyCollisionHandler chPtr inner = peek chPtr >>= inner >>= poke chPtr
+
+-- | Function type used for postStep callbacks. @space@ is the space the callback was registered on,
+-- @obj@ is the pointer value you supplied as the key, and @data@ is a user definable pointer you can use
+-- to pass in as a context value.
+type PostStepFunc
+  = Space   -- ^ space
+  -> Ptr () -- ^ obj
+  -> Ptr () -- ^ data
+  -> IO ()
+
+foreign import ccall "wrapper"
+  mkPostStep :: PostStepFunc -> IO (FunPtr PostStepFunc)
+
+-- | Add @func@ to be called before 'spaceStep' returns. @key@ and @data@ will be passed to your function.
+-- Only the first callback registered for any unique value of @key@ will be recorded.
+--
+-- It returns 'True' if the callback is scheduled and 'False' when the key has already been used.
+--
+-- __The behavior of adding a postStep callback from outside of a collision handler or query callback is undefined.__
+{# fun unsafe cpSpaceAddPostStepCallback as spaceAddPostStepCallback
+  { `Space'            -- ^ space
+  , mk* `PostStepFunc' -- ^ func
+  , `Ptr ()'           -- ^ key
+  , `Ptr ()'           -- ^ data
+  } -> `Bool' #}
+  where
+    mk f = mkPostStep f `bracket` freeHaskellFunPtr
diff --git a/src/Chiphunk/Low/Constraint.chs b/src/Chiphunk/Low/Constraint.chs
new file mode 100644
--- /dev/null
+++ b/src/Chiphunk/Low/Constraint.chs
@@ -0,0 +1,467 @@
+-- | Description: Dealing with joints/constraints
+-- Module defines utilities for operations with constraints.
+module Chiphunk.Low.Constraint
+  ( Constraint
+  , constraintBodyA
+  , constraintBodyB
+  , constraintMaxForce
+  , constraintErrorBias
+  , constraintMaxBias
+  , constraintSpace
+  , constraintCollideBodies
+  , constraintUserData
+  , constraintImpulse
+  , constraintFree
+  , pinJointNew
+  , pinJointAnchorA
+  , pinJointAnchorB
+  , pinJointDist
+  , slideJointNew
+  , slideJointAnchorA
+  , slideJointAnchorB
+  , slideJointMin
+  , slideJointMax
+  , pivotJointNew
+  , pivotJointNew2
+  , pivotJointAnchorA
+  , pivotJointAnchorB
+  , grooveJointNew
+  , grooveJointGrooveA
+  , grooveJointGrooveB
+  , grooveJointAnchorB
+  , dampedSpringNew
+  , dampedSpringAnchorA
+  , dampedSpringAnchorB
+  , dampedSpringRestLength
+  , dampedSpringStiffness
+  , dampedSpringDamping
+  , dampedRotarySpringNew
+  , dampedRotarySpringRestAngle
+  , dampedRotarySpringStiffness
+  , dampedRotarySpringDamping
+  , rotaryLimitJointNew
+  , rotaryLimitJointMin
+  , rotaryLimitJointMax
+  , ratchetJointNew
+  , ratchetJointAngle
+  , ratchetJointPhase
+  , ratchetJointRatchet
+  , gearJointNew
+  , gearJointPhase
+  , gearJointRatio
+
+  , simpleMotorNew
+  , simpleMotorRate
+  ) where
+
+import Data.StateVar
+import Foreign
+
+{# import Chiphunk.Low.Types #}
+
+#include <chipmunk/chipmunk.h>
+#include <wrapper.h>
+
+{# fun unsafe cpConstraintGetBodyA {`Constraint'} -> `Body' #}
+
+-- | The first body constraint is attached to
+constraintBodyA :: Constraint -> GettableStateVar Body
+constraintBodyA = makeGettableStateVar . cpConstraintGetBodyA
+
+{# fun unsafe cpConstraintGetBodyB {`Constraint'} -> `Body' #}
+
+-- | The second body constraint is attached to
+constraintBodyB :: Constraint -> GettableStateVar Body
+constraintBodyB = makeGettableStateVar . cpConstraintGetBodyB
+
+{# fun unsafe cpConstraintGetMaxForce {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpConstraintSetMaxForce {`Constraint', `Double'} -> `()' #}
+
+-- | The maximum force that the constraint can use to act on the two bodies.
+-- Defaults to INFINITY.
+constraintMaxForce :: Constraint -> StateVar Double
+constraintMaxForce = mkStateVar cpConstraintGetMaxForce cpConstraintSetMaxForce
+
+{# fun unsafe cpConstraintGetErrorBias {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpConstraintSetErrorBias {`Constraint', `Double'} -> `()' #}
+
+-- | The percentage of joint error that remains unfixed after a second.
+-- This works exactly the same as the collision bias property of a space,
+-- but applies to fixing error (stretching) of joints instead of overlapping collisions.
+constraintErrorBias :: Constraint -> StateVar Double
+constraintErrorBias = mkStateVar cpConstraintGetErrorBias cpConstraintSetErrorBias
+
+{# fun unsafe cpConstraintGetMaxBias {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpConstraintSetMaxBias {`Constraint', `Double'} -> `()' #}
+
+-- | Get the maximum speed at which the constraint can apply error correction.
+-- Defaults to INFINITY.
+constraintMaxBias :: Constraint -> StateVar Double
+constraintMaxBias = mkStateVar cpConstraintGetMaxBias cpConstraintSetMaxBias
+
+{# fun unsafe cpConstraintGetSpace {`Constraint'} -> `Space' #}
+
+-- | The 'Space' that constraint has been added to.
+constraintSpace :: Constraint -> GettableStateVar Space
+constraintSpace = makeGettableStateVar . cpConstraintGetSpace
+
+{# fun unsafe cpConstraintGetCollideBodies {`Constraint'} -> `Bool' #}
+
+{# fun unsafe cpConstraintSetCollideBodies {`Constraint', `Bool'} -> `()' #}
+
+-- | Constraints can be used for filtering collisions too.
+-- When two bodies collide, Chipmunk ignores the collisions
+-- if this property is set to @False@ on any constraint that connects the two bodies.
+-- Defaults to @True@.
+--
+-- This can be used to create a chain that self collides,
+-- but adjacent links in the chain do not collide.
+constraintCollideBodies :: Constraint -> StateVar Bool
+constraintCollideBodies = mkStateVar cpConstraintGetCollideBodies cpConstraintSetCollideBodies
+
+{# fun unsafe cpConstraintGetUserData {`Constraint'} -> `DataPtr' #}
+
+{# fun unsafe cpConstraintSetUserData {`Constraint', `DataPtr'} -> `()' #}
+
+-- | A user definable data pointer.
+-- Use this pointer to get a reference to the game object that owns this constraint
+-- from callbacks.
+constraintUserData :: Constraint -> StateVar DataPtr
+constraintUserData = mkStateVar cpConstraintGetUserData cpConstraintSetUserData
+
+{# fun unsafe cpConstraintGetImpulse {`Constraint'} -> `Double' #}
+
+-- | The most recent impulse that constraint applied.
+-- To convert this to a force, divide by the timestep passed to 'spaceStep'.
+-- You can use this to implement breakable joints to check
+-- if the force they attempted to apply exceeded a certain threshold.
+constraintImpulse :: Constraint -> GettableStateVar Double
+constraintImpulse = makeGettableStateVar . cpConstraintGetImpulse
+
+-- | Free function is shared by all joint types. Allocation functions are specific to each joint type.
+{# fun cpConstraintFree as constraintFree {`Constraint'} -> `()' #}
+-- no "unsafe" qualifier because I think it may trigger separte callbacks
+
+-- | Connect two bodies via anchor points on those bodies. The distance between the two anchor points is measured
+-- when the joint is created. If you want to set a specific distance, use the setter function to override it.
+{# fun unsafe cpPinJointNew as pinJointNew
+  { `Body'        -- ^ First body to connect
+  , `Body'        -- ^ Second body to connect
+  , with* %`Vect' -- ^ First anchor
+  , with* %`Vect' -- ^ Second anchor
+  } -> `Constraint' #}
+
+{# fun unsafe w_cpPinJointGetAnchorA {`Constraint', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpPinJointSetAnchorA {`Constraint', with* %`Vect'} -> `()' #}
+
+-- | Anchor on first body.
+pinJointAnchorA :: Constraint -> StateVar Vect
+pinJointAnchorA = mkStateVar w_cpPinJointGetAnchorA cpPinJointSetAnchorA
+
+{# fun unsafe w_cpPinJointGetAnchorB {`Constraint', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpPinJointSetAnchorB {`Constraint', with* %`Vect'} -> `()' #}
+
+-- | Anchor on second body.
+pinJointAnchorB :: Constraint -> StateVar Vect
+pinJointAnchorB = mkStateVar w_cpPinJointGetAnchorB cpPinJointSetAnchorB
+
+{# fun unsafe cpPinJointGetDist {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpPinJointSetDist {`Constraint', `Double'} -> `()' #}
+
+-- | Desired distance the joint will try to enforce.
+pinJointDist :: Constraint -> StateVar Double
+pinJointDist = mkStateVar cpPinJointGetDist cpPinJointSetDist
+
+-- | Connect two bodies via anchor points forcing distance to remain in range.
+{# fun unsafe cpSlideJointNew as slideJointNew
+  { `Body'        -- ^ First body to connect
+  , `Body'        -- ^ Second body to connect
+  , with* %`Vect' -- ^ First anchor
+  , with* %`Vect' -- ^ Second anchor
+  , `Double'      -- ^ Minimum allowed distance
+  , `Double'      -- ^ Maximum allowed distance
+  } -> `Constraint' #}
+
+{# fun unsafe w_cpSlideJointGetAnchorA {`Constraint', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpSlideJointSetAnchorA  {`Constraint', with* %`Vect'} -> `()' #}
+
+-- | Anchor on first body.
+slideJointAnchorA :: Constraint -> StateVar Vect
+slideJointAnchorA = mkStateVar w_cpSlideJointGetAnchorA cpSlideJointSetAnchorA
+
+{# fun unsafe w_cpSlideJointGetAnchorB {`Constraint', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpSlideJointSetAnchorB {`Constraint', with* %`Vect'} -> `()' #}
+
+-- | Anchor on second body.
+slideJointAnchorB :: Constraint -> StateVar Vect
+slideJointAnchorB = mkStateVar w_cpSlideJointGetAnchorB cpSlideJointSetAnchorB
+
+{# fun unsafe cpSlideJointGetMin {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpSlideJointSetMin {`Constraint', `Double'} -> `()' #}
+
+-- | The minimum distance the joint will try to enforce.
+slideJointMin :: Constraint -> StateVar Double
+slideJointMin = mkStateVar cpSlideJointGetMin cpSlideJointSetMin
+
+{# fun unsafe cpSlideJointGetMax {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpSlideJointSetMax {`Constraint', `Double'} -> `()' #}
+
+-- | The maximum distance the joint will try to enforce.
+slideJointMax :: Constraint -> StateVar Double
+slideJointMax = mkStateVar cpSlideJointGetMax cpSlideJointSetMax
+
+-- | Because the pivot location is given in world coordinates,
+-- you must have the bodies moved into the correct positions already.
+{# fun unsafe cpPivotJointNew as pivotJointNew
+  { `Body'        -- ^ First body to connect
+  , `Body'        -- ^ Second body to connect
+  , with* %`Vect' -- ^ Point in the world coordinates of the pivot
+  } -> `Constraint' #}
+
+-- | Alternatively you can specify the joint based on a pair of anchor points,
+-- but make sure you have the bodies in the right place as the joint will fix itself
+-- as soon as you start simulating the space.
+{# fun unsafe cpPivotJointNew2 as pivotJointNew2
+  { `Body'        -- ^ First body to connect
+  , `Body'        -- ^ Second body to connect
+  , with* %`Vect' -- ^ Anchor on first body
+  , with* %`Vect' -- ^ Anchor on second body
+  } -> `Constraint' #}
+
+{# fun unsafe w_cpPivotJointGetAnchorA {`Constraint', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpPivotJointSetAnchorA {`Constraint', with* %`Vect'} -> `()' #}
+
+-- | Anchor on first body.
+pivotJointAnchorA :: Constraint -> StateVar Vect
+pivotJointAnchorA = mkStateVar w_cpPivotJointGetAnchorA cpPivotJointSetAnchorA
+
+{# fun unsafe w_cpPivotJointGetAnchorB {`Constraint', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpPivotJointSetAnchorB {`Constraint', with* %`Vect'} -> `()' #}
+
+-- | Anchor on second body.
+pivotJointAnchorB :: Constraint -> StateVar Vect
+pivotJointAnchorB = mkStateVar w_cpPivotJointGetAnchorB cpPivotJointSetAnchorB
+
+-- | Pivot is attached to groove on first body and to anchor on the second. All coordinates are body local.
+{# fun unsafe cpGrooveJointNew as grooveJointNew
+  { `Body'        -- ^ First body to connect
+  , `Body'        -- ^ Second body to connect
+  , with* %`Vect' -- ^ First endpoint of groove (on first body)
+  , with* %`Vect' -- ^ Second endpoint of groove (on first body)
+  , with* %`Vect' -- ^ Anchor (on second body)
+  } -> `Constraint' #}
+
+{# fun unsafe w_cpGrooveJointGetGrooveA {`Constraint', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpGrooveJointSetGrooveA {`Constraint', with* %`Vect'} -> `()' #}
+
+-- | First endpoint of groove (on first body).
+grooveJointGrooveA :: Constraint -> StateVar Vect
+grooveJointGrooveA = mkStateVar w_cpGrooveJointGetGrooveA cpGrooveJointSetGrooveA
+
+{# fun unsafe w_cpGrooveJointGetGrooveB {`Constraint', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpGrooveJointSetGrooveB {`Constraint', with* %`Vect'} -> `()' #}
+
+-- | Second endpoint of groove (on first body).
+grooveJointGrooveB :: Constraint -> StateVar Vect
+grooveJointGrooveB = mkStateVar w_cpGrooveJointGetGrooveB cpGrooveJointSetGrooveB
+
+{# fun unsafe w_cpGrooveJointGetAnchorB {`Constraint', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpGrooveJointSetAnchorB {`Constraint', with* %`Vect'} -> `()' #}
+
+-- | Anchor on second body.
+grooveJointAnchorB :: Constraint -> StateVar Vect
+grooveJointAnchorB = mkStateVar w_cpGrooveJointGetAnchorB cpGrooveJointSetAnchorB
+
+-- | Defined much like a slide joint.
+{# fun unsafe cpDampedSpringNew as dampedSpringNew
+  { `Body'        -- ^ First body to connect
+  , `Body'        -- ^ Second body to connect
+  , with* %`Vect' -- ^ First anchor
+  , with* %`Vect' -- ^ Second anchor
+  , `Double'      -- ^ Distance the spring wants to be
+  , `Double'      -- ^ Spring constant (<http://en.wikipedia.org/wiki/Young%27s_modulus Young's modulus>)
+  , `Double'      -- ^ How soft to make damping of the spring
+  } -> `Constraint' #}
+
+{# fun unsafe w_cpDampedSpringGetAnchorA {`Constraint', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpDampedSpringSetAnchorA {`Constraint', with* %`Vect'} -> `()' #}
+
+-- | Anchor on first body.
+dampedSpringAnchorA :: Constraint -> StateVar Vect
+dampedSpringAnchorA = mkStateVar w_cpDampedSpringGetAnchorA cpDampedSpringSetAnchorA
+
+{# fun unsafe w_cpDampedSpringGetAnchorB {`Constraint', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpDampedSpringSetAnchorB {`Constraint', with* %`Vect'} -> `()' #}
+
+-- | Anchor on second body.
+dampedSpringAnchorB :: Constraint -> StateVar Vect
+dampedSpringAnchorB = mkStateVar w_cpDampedSpringGetAnchorB cpDampedSpringSetAnchorB
+
+{# fun unsafe cpDampedSpringGetRestLength {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpDampedSpringSetRestLength {`Constraint', `Double'} -> `()' #}
+
+-- | Desired distance the spring will try to enforce.
+dampedSpringRestLength :: Constraint -> StateVar Double
+dampedSpringRestLength = mkStateVar cpDampedSpringGetRestLength cpDampedSpringSetRestLength
+
+{# fun unsafe cpDampedSpringGetStiffness {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpDampedSpringSetStiffness {`Constraint', `Double'} -> `()' #}
+
+-- | Spring stiffness
+dampedSpringStiffness :: Constraint -> StateVar Double
+dampedSpringStiffness = mkStateVar cpDampedSpringGetStiffness cpDampedSpringSetStiffness
+
+{# fun unsafe cpDampedSpringGetDamping {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpDampedSpringSetDamping {`Constraint', `Double'} -> `()' #}
+
+-- | Spring damping
+dampedSpringDamping :: Constraint -> StateVar Double
+dampedSpringDamping = mkStateVar cpDampedSpringGetDamping cpDampedSpringSetDamping
+
+-- | Create new damped rotary spring constraint
+{# fun unsafe cpDampedRotarySpringNew as dampedRotarySpringNew
+  { `Body'    -- ^ First body to connect
+  , `Body'    -- ^ Second body to connect
+  , `Double'  -- ^ Relative angle in radians that the bodies want to have
+  , `Double'  -- ^ Spring constant (stiffness)
+  , `Double'  -- ^ Spring damping
+  } -> `Constraint' #}
+
+{# fun unsafe cpDampedRotarySpringGetRestAngle {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpDampedRotarySpringSetRestAngle {`Constraint', `Double'} -> `()' #}
+
+-- | Set desired angle in radians the spring will try to enforce.
+dampedRotarySpringRestAngle :: Constraint -> StateVar Double
+dampedRotarySpringRestAngle = mkStateVar cpDampedRotarySpringGetRestAngle cpDampedRotarySpringSetRestAngle
+
+{# fun unsafe cpDampedRotarySpringGetStiffness {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpDampedRotarySpringSetStiffness {`Constraint', `Double'} -> `()' #}
+
+-- | Spring stiffness.
+dampedRotarySpringStiffness :: Constraint -> StateVar Double
+dampedRotarySpringStiffness = mkStateVar cpDampedRotarySpringGetStiffness cpDampedRotarySpringSetStiffness
+
+{# fun unsafe cpDampedRotarySpringGetDamping {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpDampedRotarySpringSetDamping {`Constraint', `Double'} -> `()' #}
+
+-- | Spring damping.
+dampedRotarySpringDamping :: Constraint -> StateVar Double
+dampedRotarySpringDamping = mkStateVar cpDampedRotarySpringGetDamping cpDampedRotarySpringSetDamping
+
+-- | Create new rotation limiting joint
+{# fun unsafe cpRotaryLimitJointNew as rotaryLimitJointNew
+  { `Body'    -- ^ First body to connect
+  , `Body'    -- ^ Second body to connect
+  , `Double'  -- ^ Minimum angle in radians the joint will enforce
+  , `Double'  -- ^ Maximum angle in radians the joint will enforce
+  } -> `Constraint' #}
+
+{# fun unsafe cpRotaryLimitJointGetMin {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpRotaryLimitJointSetMin {`Constraint', `Double'} -> `()' #}
+
+-- | Minimum angle in radians the joint will try to enforce.
+rotaryLimitJointMin :: Constraint -> StateVar Double
+rotaryLimitJointMin = mkStateVar cpRotaryLimitJointGetMin cpRotaryLimitJointSetMin
+
+{# fun unsafe cpRotaryLimitJointGetMax {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpRotaryLimitJointSetMax {`Constraint', `Double'} -> `()' #}
+
+-- | Maximum angle in radians the joint will try to enforce.
+rotaryLimitJointMax :: Constraint -> StateVar Double
+rotaryLimitJointMax = mkStateVar cpRotaryLimitJointGetMax cpRotaryLimitJointSetMax
+
+-- | Allocate and initialize a ratchet joint.
+{# fun unsafe cpRatchetJointNew as ratchetJointNew
+  { `Body'    -- ^ First body to connect
+  , `Body'    -- ^ Second body to connect
+  , `Double'  -- ^ The initial offset to use when deciding where the ratchet angles are.
+  , `Double'  -- ^ The distance between “clicks”
+  } -> `Constraint' #}
+
+{# fun unsafe cpRatchetJointGetAngle {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpRatchetJointSetAngle {`Constraint', `Double'} -> `()' #}
+
+-- | The angle of the current ratchet tooth.
+ratchetJointAngle :: Constraint -> StateVar Double
+ratchetJointAngle = mkStateVar cpRatchetJointGetAngle cpRatchetJointSetAngle
+
+{# fun unsafe cpRatchetJointGetPhase {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpRatchetJointSetPhase {`Constraint', `Double'} -> `()' #}
+
+-- | The phase offset of the ratchet.
+ratchetJointPhase :: Constraint -> StateVar Double
+ratchetJointPhase = mkStateVar cpRatchetJointGetPhase cpRatchetJointSetPhase
+
+{# fun unsafe cpRatchetJointGetRatchet {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpRatchetJointSetRatchet {`Constraint', `Double'} -> `()' #}
+
+-- | The angular distance of each ratchet.
+ratchetJointRatchet :: Constraint -> StateVar Double
+ratchetJointRatchet = mkStateVar cpRatchetJointGetRatchet cpRatchetJointSetRatchet
+
+-- | Allocate and initialize a gear joint.
+{# fun unsafe cpGearJointNew as gearJointNew
+  { `Body'    -- ^ First body to connect
+  , `Body'    -- ^ Second body to connect
+  , `Double'  -- ^ The initial angular offset of the two bodies.
+  , `Double'  -- ^ Ratio measures in absolute terms
+  } -> `Constraint' #}
+
+{# fun unsafe cpGearJointGetPhase {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpGearJointSetPhase {`Constraint', `Double'} -> `()' #}
+
+-- | Phase offset of the ratchet.
+gearJointPhase :: Constraint -> StateVar Double
+gearJointPhase = mkStateVar cpGearJointGetPhase cpGearJointSetPhase
+
+{# fun unsafe cpGearJointGetRatio {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpGearJointSetRatio {`Constraint', `Double'} -> `()' #}
+
+-- | Ratio of the ratchet
+gearJointRatio :: Constraint -> StateVar Double
+gearJointRatio = mkStateVar cpGearJointGetRatio cpGearJointSetRatio
+
+-- | Allocate and initialize a simple motor.
+{# fun unsafe cpSimpleMotorNew as simpleMotorNew
+  { `Body'    -- ^ First body to connect
+  , `Body'    -- ^ Second body to connect
+  , `Double'  -- ^ The desired relative angular velocity.
+  } -> `Constraint' #}
+
+{# fun unsafe cpSimpleMotorGetRate {`Constraint'} -> `Double' #}
+
+{# fun unsafe cpSimpleMotorSetRate {`Constraint', `Double'} -> `()' #}
+
+-- | Ratio of angular velocities.
+simpleMotorRate :: Constraint -> StateVar Double
+simpleMotorRate = mkStateVar cpSimpleMotorGetRate cpSimpleMotorSetRate
diff --git a/src/Chiphunk/Low/Helper.chs b/src/Chiphunk/Low/Helper.chs
new file mode 100644
--- /dev/null
+++ b/src/Chiphunk/Low/Helper.chs
@@ -0,0 +1,99 @@
+-- | Description: Helpers functions mostly for estimating certain measures.
+-- Module provides helper function mostly for estimating certain measures.
+module Chiphunk.Low.Helper
+  ( momentForCircle
+  , momentForSegment
+  , momentForPoly
+  , momentForBox
+  , areaForCircle
+  , areaForSegment
+  , areaForPoly
+  , centroidForPoly
+  , convexHull
+  ) where
+
+import Data.VectorSpace
+import Foreign
+import System.IO.Unsafe
+
+import Chiphunk.Low.Internal
+
+{# import Chiphunk.Low.Types #}
+
+#include <chipmunk/chipmunk.h>
+#include <wrapper.h>
+
+-- | Calculate the moment of inertia for a hollow circle, @r1@ and @r2@ are the inner and outer diameters
+-- in no particular order. (A solid circle has an inner diameter of 0)
+momentForCircle
+  :: Double -- ^ Mass
+  -> Double -- ^ r1
+  -> Double -- ^ r2
+  -> Vect   -- ^ Offset
+  -> Double
+momentForCircle m r1 r2 offs = m * (0.5 * (r1 * r1 + r2 * r2) + magnitudeSq offs)
+
+-- | Calculate the moment of inertia for a line segment. The endpoints @a@ and @b@ are relative to the body.
+momentForSegment
+  :: Double -- ^ Mass
+  -> Vect   -- ^ a
+  -> Vect   -- ^ b
+  -> Double -- ^ Thickness
+  -> Double
+momentForSegment m a b r = m * ((len * len + 4 * r * r) / 12 + magnitudeSq offs)
+  where
+    offs = lerp a b 0.5
+    len  = magnitude (b ^-^ a) + 2 * r
+
+-- | Calculate the moment of inertia for a solid polygon shape assuming its center of gravity is at its centroid.
+-- The offset is added to each vertex.
+{# fun pure unsafe cpMomentForPoly as momentForPoly
+  { `Double'            -- ^ Mass
+  , withList* `[Vect]'& -- ^ Vertexes
+  , with* %`Vect'       -- ^ Offset
+  , `Double'            -- ^ Thickness
+  } -> `Double' #}
+
+-- | Calculate the moment of inertia for a solid box centered on the body.
+momentForBox
+  :: Double -- ^ Mass
+  -> Double -- ^ Width
+  -> Double -- ^ Height
+  -> Double
+momentForBox m w h = m * (w * w + h * h) / 12
+
+-- | Area of a hollow circle.
+areaForCircle
+  :: Double -- ^ r1
+  -> Double -- ^ r2
+  -> Double
+areaForCircle r1 r2 = pi * abs (r1 * r1 - r2 * r2)
+
+-- | Area of a beveled segment. (Will always be zero if radius is zero)
+areaForSegment
+  :: Vect   -- ^ One end
+  -> Vect   -- ^ Other end
+  -> Double -- ^ Thickness
+  -> Double
+areaForSegment v1 v2 r = magnitude (v1 ^-^ v2) * 2 * r + pi * r * r
+
+-- | Signed area of a polygon shape. Returns a negative number for polygons with a clockwise winding.
+{# fun pure unsafe cpAreaForPoly as areaForPoly
+  { withList* `[Vect]'& -- ^ Vertexes
+  , `Double'            -- ^ Thickness
+  } -> `Double' #}
+
+-- | Calculate the centroid for a polygon.
+{# fun pure unsafe w_cpCentroidForPoly as centroidForPoly {withList* `[Vect]'&, alloca- `Vect' peek*} -> `()' #}
+
+-- | Calculate the convex hull of a given set of points.
+convexHull
+  :: [Vect]        -- ^ Set of vertexes
+  -> Double        -- ^ Allowed amount to shrink the hull when simplifying it. A tolerance of 0 creates an exact hull.
+  -> ([Vect], Int) -- ^ Second element is index of first output vertex in input list.
+convexHull vs tol = unsafePerformIO $
+  withArray vs $ \pVs ->
+  allocaArray (length vs) $ \pRes ->
+  alloca $ \pFst -> do
+    n <- {# call cpConvexHull as c_convexHull #} (fromIntegral $ length vs) pVs pRes pFst (realToFrac tol)
+    (,) <$> peekArray (fromIntegral n) pRes <*> (fromIntegral <$> peek pFst)
diff --git a/src/Chiphunk/Low/Internal.hs b/src/Chiphunk/Low/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Chiphunk/Low/Internal.hs
@@ -0,0 +1,9 @@
+module Chiphunk.Low.Internal where
+
+import Foreign
+import Foreign.C.Types
+
+-- | Internal helper function to convert list of storable elements to tuple of length and elements stored in memory
+-- and executes IO actions, cleaning up afterwards.
+withList :: Storable a => [a] -> ((CInt, Ptr a) -> IO b) -> IO b
+withList xs inner = withArray xs $ \p -> inner (fromIntegral $ length xs, castPtr p)
diff --git a/src/Chiphunk/Low/Math.hs b/src/Chiphunk/Low/Math.hs
new file mode 100644
--- /dev/null
+++ b/src/Chiphunk/Low/Math.hs
@@ -0,0 +1,32 @@
+-- | Description: Math helpers.
+-- Module provides mathematics helper functions.
+module Chiphunk.Low.Math where
+
+import Data.VectorSpace
+
+-- | Clamp @f@ to be between @min@ and @max@
+fClamp
+  :: Double -- ^ f
+  -> Double -- ^ min
+  -> Double -- ^ max
+  -> Double
+fClamp x a b
+  | x < a     = a
+  | x > b     = b
+  | otherwise = x
+
+-- | Linearly interpolate between @f1@ and @f2@
+fLerp
+  :: Double -- ^ f1
+  -> Double -- ^ f2
+  -> Double
+  -> Double
+fLerp = lerp
+
+-- | Linearly interpolate from @f1@ towards @f2@ by no more than @d@.
+fLerpConst
+  :: Double -- ^ f1
+  -> Double -- ^ f2
+  -> Double -- ^ d
+  -> Double
+fLerpConst x y d = x + fClamp (y - x) (-d) d
diff --git a/src/Chiphunk/Low/Shape.chs b/src/Chiphunk/Low/Shape.chs
new file mode 100644
--- /dev/null
+++ b/src/Chiphunk/Low/Shape.chs
@@ -0,0 +1,226 @@
+-- | Description: Shapes manipulations
+-- Module provides access to the shapes which define collisions of rigid bodies.
+module Chiphunk.Low.Shape
+  ( Shape
+  , shapeBody
+  , shapeBB
+  , shapeSensor
+  , shapeElasticity
+  , shapeFriction
+  , shapeSurfaceVelocity
+  , shapeCollisionType
+  , ShapeFilter (..)
+  , ShapeFilterPtr
+  , shapeFilter
+  , shapeSpace
+  , shapeUserData
+  , shapeFree
+  , shapeCacheBB
+  , shapeUpdate
+  , circleShapeNew
+  , segmentShapeNew
+  , segmentShapeNeighbors
+  , polyShapeNew
+  , polyShapeNewRaw
+  , boxShapeNew
+  , boxShapeNew2
+  ) where
+
+import Foreign
+
+import Chiphunk.Low.Internal
+import Data.StateVar
+
+{# import Chiphunk.Low.Types #}
+
+#include <chipmunk/chipmunk.h>
+#include <wrapper.h>
+
+{# fun unsafe cpShapeGetBody {`Shape'} -> `Body' #}
+
+{# fun unsafe cpShapeSetBody {`Shape', `Body'} -> `()' #}
+
+-- | The rigid body the shape is attached to.
+-- Can only be set when the shape is not added to a space.
+shapeBody :: Shape -> StateVar Body
+shapeBody = mkStateVar cpShapeGetBody cpShapeSetBody
+
+{# fun unsafe w_cpShapeGetBB {`Shape', alloca- `BB' peek*} -> `()' #}
+
+-- | The bounding box of the shape.
+-- Only guaranteed to be valid after 'shapeCacheBB' or 'spaceStep' is called.
+-- Moving a body that a shape is connected to does not update its bounding box.
+-- For shapes used for queries that aren’t attached to bodies, you can also use 'shapeUpdate'.
+shapeBB :: Shape -> GettableStateVar BB
+shapeBB = makeGettableStateVar . w_cpShapeGetBB
+
+{# fun unsafe cpShapeGetSensor {`Shape'} -> `Bool' #}
+
+{# fun unsafe cpShapeSetSensor {`Shape', `Bool'} -> `()' #}
+
+-- | A boolean value if this shape is a sensor or not.
+-- Sensors only call collision callbacks, and never generate real collisions.
+shapeSensor :: Shape -> StateVar Bool
+shapeSensor = mkStateVar cpShapeGetSensor cpShapeSetSensor
+
+{# fun unsafe cpShapeGetElasticity {`Shape'} -> `Double' #}
+
+{# fun unsafe cpShapeSetElasticity {`Shape', `Double'} -> `()' #}
+
+-- | Elasticity of the shape.
+-- A value of 0.0 gives no bounce, while a value of 1.0 will give a “perfect” bounce.
+-- However due to inaccuracies in the simulation using 1.0 or greater is not recommended however.
+--
+-- The elasticity for a collision is found by multiplying the elasticity of the individual shapes together.
+shapeElasticity :: Shape -> StateVar Double
+shapeElasticity = mkStateVar cpShapeGetElasticity cpShapeSetElasticity
+
+{# fun unsafe cpShapeGetFriction {`Shape'} -> `Double' #}
+
+{# fun unsafe cpShapeSetFriction {`Shape', `Double'} -> `()' #}
+
+-- | Friction coefficient.
+-- Chipmunk uses the Coulomb friction model, a value of 0.0 is frictionless.
+--
+-- The friction for a collision is found by multiplying the friction of the individual shapes together.
+-- <http://www.roymech.co.uk/Useful_Tables/Tribology/co_of_frict.htm Table of friction coefficients.>
+shapeFriction :: Shape -> StateVar Double
+shapeFriction = mkStateVar cpShapeGetFriction cpShapeSetFriction
+
+{# fun unsafe w_cpShapeGetSurfaceVelocity {`Shape', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpShapeSetSurfaceVelocity {`Shape', with* %`Vect'} -> `()' #}
+
+-- | The surface velocity of the object.
+-- Useful for creating conveyor belts or players that move around.
+-- This value is only used when calculating friction, not resolving the collision.
+shapeSurfaceVelocity :: Shape -> StateVar Vect
+shapeSurfaceVelocity = mkStateVar w_cpShapeGetSurfaceVelocity cpShapeSetSurfaceVelocity
+
+{# fun unsafe cpShapeGetCollisionType {`Shape'} -> `CollisionType' fromIntegral #}
+
+{# fun unsafe cpShapeSetCollisionType {`Shape', fromIntegral `CollisionType'} -> `()' #}
+
+-- | Collision type of this shape.
+-- | You can assign types to Chipmunk collision shapes
+-- that trigger callbacks when objects of certain types touch.
+-- See the callbacks section for more information.
+shapeCollisionType :: Shape -> StateVar CollisionType
+shapeCollisionType = mkStateVar cpShapeGetCollisionType cpShapeSetCollisionType
+
+-- | Fast collision filtering type that is used to determine if two objects collide
+-- before calling collision or query callbacks.
+data ShapeFilter = ShapeFilter
+  { sfGroup :: !WordPtr
+  , sfCategories :: !Word32
+  , sfMask :: !Word32
+  } deriving Show
+
+instance Storable ShapeFilter where
+  sizeOf _    = {# sizeof cpShapeFilter #}
+  alignment _ = {# alignof cpShapeFilter #}
+  poke p (ShapeFilter g c m) = do
+    {# set cpShapeFilter->group #} p      $ fromIntegral g
+    {# set cpShapeFilter->categories #} p $ fromIntegral c
+    {# set cpShapeFilter->mask #} p       $ fromIntegral m
+  peek p = ShapeFilter <$> (fromIntegral <$> {# get cpShapeFilter->group #} p)
+                       <*> (fromIntegral <$> {# get cpShapeFilter->categories #} p)
+                       <*> (fromIntegral <$> {# get cpShapeFilter->mask #} p)
+
+-- | Pointer to 'ShapeFilter'
+{# pointer *cpShapeFilter as ShapeFilterPtr -> ShapeFilter #}
+
+{# fun unsafe w_cpShapeGetFilter {`Shape', alloca- `ShapeFilter' peek*} -> `()' #}
+
+{# fun unsafe cpShapeSetFilter {`Shape', with* %`ShapeFilter'} -> `()' #}
+
+-- | The collision filter for this shape. See Filtering Collisions for more information.
+shapeFilter :: Shape -> StateVar ShapeFilter
+shapeFilter = mkStateVar w_cpShapeGetFilter cpShapeSetFilter
+
+{# fun unsafe cpShapeGetSpace {`Shape'} -> `Space' #}
+
+-- | The 'Space' that @shape@ has been added to.
+shapeSpace :: Shape -> GettableStateVar Space
+shapeSpace = makeGettableStateVar . cpShapeGetSpace
+
+{# fun unsafe cpShapeGetUserData {`Shape'} -> `DataPtr' #}
+
+{# fun unsafe cpShapeSetUserData {`Shape', `DataPtr'} -> `()' #}
+
+-- | A user definable data pointer.
+-- If you set this to point at the game object the shapes is for,
+-- then you can access your game object from Chipmunk callbacks.
+shapeUserData :: Shape -> StateVar DataPtr
+shapeUserData = mkStateVar cpShapeGetUserData cpShapeSetUserData
+
+-- | Deallocates shape.
+{# fun cpShapeFree as shapeFree {`Shape'} -> `()' #}
+-- no "unsafe" qualifier because I think it may trigger separte callbacks
+
+-- | Synchronizes @shape@ with the body its attached to.
+{# fun unsafe w_cpShapeCacheBB as shapeCacheBB
+  { `Shape'            -- ^ shape
+  , alloca- `BB' peek*
+  } -> `()' #}
+
+-- | Sets the position and rotation of the shape
+{# fun unsafe w_cpShapeUpdate as shapeUpdate
+  { `Shape'            -- ^ @shape@
+  , with* %`Transform'
+  , alloca- `BB' peek*
+  } -> `()' #}
+
+-- | Create new circle-like shape.
+{# fun unsafe cpCircleShapeNew as circleShapeNew
+  { `Body'        -- ^ The body to attach the circle to.
+  , `Double'      -- ^ Radius of the circle.
+  , with* %`Vect' -- ^ Offset from the body's center of gravity in body local coordinates.
+  } -> `Shape' #}
+
+-- | Create new segment-shaped shape.
+{# fun unsafe cpSegmentShapeNew as segmentShapeNew
+  { `Body'        -- ^ The body to attach the segment to.
+  , with* %`Vect' -- ^ One endpoint.
+  , with* %`Vect' -- ^ Another endpoint.
+  , `Double'      -- ^ The thickness of the segment.
+  } -> `Shape' #}
+
+{# fun unsafe cpSegmentShapeSetNeighbors {`Shape', with* %`Vect', with* %`Vect'} -> `()' #}
+
+-- | When you have a number of segment shapes that are all joined together,
+-- things can still collide with the “cracks” between the segments.
+-- By setting the neighbor segment endpoints
+-- you can tell Chipmunk to avoid colliding with the inner parts of the crack.
+segmentShapeNeighbors :: Shape -> SettableStateVar (Vect, Vect)
+segmentShapeNeighbors shape =
+  makeSettableStateVar $ \(v1, v2) ->
+    cpSegmentShapeSetNeighbors shape v1 v2
+
+-- | A convex hull will be calculated from the vertexes automatically.
+-- The polygon shape will be created with a radius, increasing the size of the shape.
+{# fun unsafe cpPolyShapeNew as polyShapeNew
+  { `Body'              -- ^ The body to attach the poly to.
+  , withList* `[Vect]'& -- ^ The array of 'Vect' structs.
+  , with* %`Transform'  -- ^ The transform that will be applied to every vertex.
+  , `Double'            -- ^ Radius.
+  } -> `Shape' #}
+
+-- | Alternate constructors for poly shapes. This version does not apply a transform nor does it create a convex hull.
+-- Verticies must be provided with a counter-clockwise winding.
+{# fun unsafe cpPolyShapeNewRaw as polyShapeNewRaw {`Body', withList* `[Vect]'&, `Double'} -> `Shape' #}
+
+-- | Createa box shape from dimensions.
+{# fun unsafe cpBoxShapeNew as boxShapeNew
+  { `Body'    -- ^ The body to attach to
+  , `Double'  -- ^ Box width
+  , `Double'  -- ^ Box height
+  , `Double'  -- ^ Radius
+  } -> `Shape' #}
+
+-- | Alternative to 'boxShapeNew' using 'BB' to set size.
+{# fun unsafe cpBoxShapeNew2 as boxShapeNew2
+  { `Body'      -- ^ The body to attach to
+  , with* %`BB' -- ^ Shape size
+  , `Double'    -- ^ Radius
+  } -> `Shape' #}
diff --git a/src/Chiphunk/Low/Space.chs b/src/Chiphunk/Low/Space.chs
new file mode 100644
--- /dev/null
+++ b/src/Chiphunk/Low/Space.chs
@@ -0,0 +1,266 @@
+-- | Description: Manipulate space
+-- Module defined utilities for manipulating spaces.
+module Chiphunk.Low.Space
+  ( Space
+  , spaceIterations
+  , spaceGravity
+  , spaceDamping
+  , spaceIdleSpeedThreshold
+  , spaceSleepTimeThreshold
+  , spaceCollisionSlop
+  , spaceCollisionBias
+  , spaceCollisionPersistence
+  , spaceCurrentTimeStep
+  , spaceIsLocked
+  , spaceUserData
+  , spaceStaticBody
+  , spaceNew
+  , spaceFree
+  , spaceAddShape
+  , spaceAddBody
+  , spaceAddConstraint
+  , spaceRemoveShape
+  , spaceRemoveBody
+  , spaceRemoveConstraint
+  , spaceContainsShape
+  , spaceContainsBody
+  , spaceContainsConstraint
+  , spaceReindexShape
+  , spaceReindexShapesForBody
+  , spaceReindexStatic
+  , SpaceBodyIteratorFunc
+  , spaceEachBody
+  , SpaceShapeIteratorFunc
+  , spaceEachShape
+  , SpaceConstraintIteratorFunc
+  , spaceEachConstraint
+  , spaceStep
+  ) where
+
+import Control.Exception.Safe
+import Data.StateVar
+import Foreign
+
+import Chiphunk.Low.Vect
+{# import Chiphunk.Low.Types #}
+
+#include <chipmunk/chipmunk.h>
+#include <wrapper.h>
+
+{# fun unsafe cpSpaceGetIterations {`Space'} -> `Int' #}
+
+{# fun unsafe cpSpaceSetIterations {`Space', `Int'} -> `()' #}
+
+-- | Iterations allow you to control the accuracy of the solver.
+-- Defaults to 10. See above for more information.
+spaceIterations :: Space -> StateVar Int
+spaceIterations = mkStateVar cpSpaceGetIterations cpSpaceSetIterations
+
+{# fun unsafe w_cpSpaceGetGravity {`Space', alloca- `Vect' peek*} -> `()' #}
+
+{# fun unsafe cpSpaceSetGravity {`Space', with* %`Vect'} -> `()' #}
+
+-- | Global gravity applied to the space. Defaults to 'vZero'.
+-- Can be overridden on a per body basis by writing custom integration functions.
+-- Changing the gravity will activate all sleeping bodies in the space.
+spaceGravity :: Space -> StateVar Vect
+spaceGravity = mkStateVar w_cpSpaceGetGravity cpSpaceSetGravity
+
+{# fun unsafe cpSpaceGetDamping {`Space'} -> `Double' #}
+
+{# fun unsafe cpSpaceSetDamping {`Space', `Double'} -> `()' #}
+
+-- | Amount of simple damping to apply to the space.
+-- A value of 0.9 means that each body will lose 10% of its velocity per second.
+-- Defaults to 1. Like gravity, it can be overridden on a per body basis.
+spaceDamping :: Space -> StateVar Double
+spaceDamping = mkStateVar cpSpaceGetDamping cpSpaceSetDamping
+
+{# fun unsafe cpSpaceGetIdleSpeedThreshold {`Space'} -> `Double' #}
+
+{# fun unsafe cpSpaceSetIdleSpeedThreshold {`Space', `Double'} -> `()' #}
+
+-- | Speed threshold for a body to be considered idle.
+-- The default value of 0 means the space estimates a good threshold based on gravity.
+spaceIdleSpeedThreshold :: Space -> StateVar Double
+spaceIdleSpeedThreshold = mkStateVar cpSpaceGetIdleSpeedThreshold cpSpaceSetIdleSpeedThreshold
+
+{# fun unsafe cpSpaceGetSleepTimeThreshold {`Space'} -> `Double' #}
+
+{# fun unsafe cpSpaceSetSleepTimeThreshold {`Space', `Double'} -> `()' #}
+
+-- | Time a group of bodies must remain idle in order to fall asleep.
+-- The default value of INFINITY disables the sleeping feature.
+spaceSleepTimeThreshold :: Space -> StateVar Double
+spaceSleepTimeThreshold = mkStateVar cpSpaceGetSleepTimeThreshold cpSpaceSetSleepTimeThreshold
+
+{# fun unsafe cpSpaceGetCollisionSlop {`Space'} -> `Double' #}
+
+{# fun unsafe cpSpaceSetCollisionSlop {`Space', `Double'} -> `()' #}
+
+-- | Amount of overlap between shapes that is allowed.
+-- To improve stability, set this as high as you can without noticable overlapping.
+-- It defaults to @0.1@.
+spaceCollisionSlop :: Space -> StateVar Double
+spaceCollisionSlop = mkStateVar cpSpaceGetCollisionSlop cpSpaceSetCollisionSlop
+
+{# fun unsafe cpSpaceGetCollisionBias {`Space'} -> `Double' #}
+
+{# fun unsafe cpSpaceSetCollisionBias {`Space', `Double'} -> `()' #}
+
+-- | Chipmunk allows fast moving objects to overlap, then fixes the overlap over time.
+-- Overlapping objects are unavoidable even if swept collisions are supported,
+-- and this is an efficient and stable way to deal with overlapping objects.
+-- The bias value controls what percentage of overlap remains unfixed
+-- after a second and defaults to ~0.2%.
+--
+-- Valid values are in the range from 0 to 1,
+-- but using 0 is not recommended for stability reasons.
+--
+-- The default value is calculated as @(1.0 - 0.1) ^ 60@
+-- meaning that Chipmunk attempts to correct 10% of error ever 1/60th of a second.
+--
+-- __Note__: Very very few games will need to change this value.
+spaceCollisionBias :: Space -> StateVar Double
+spaceCollisionBias = mkStateVar cpSpaceGetCollisionBias cpSpaceSetCollisionBias
+
+{# fun unsafe cpSpaceGetCollisionPersistence {`Space'} -> `Word32' #}
+
+{# fun unsafe cpSpaceSetCollisionPersistence {`Space', `Word32'} -> `()' #}
+
+-- | The number of frames the space keeps collision solutions around for.
+-- Helps prevent jittering contacts from getting worse.
+-- This defaults to 3 and very very very few games will need to change this value.
+spaceCollisionPersistence :: Space -> StateVar Word32
+spaceCollisionPersistence = mkStateVar cpSpaceGetCollisionPersistence cpSpaceSetCollisionPersistence
+
+{# fun unsafe cpSpaceGetCurrentTimeStep {`Space'} -> `Double' #}
+
+-- | The current (if you are in a callback from 'spaceStep')
+-- or most recent (outside of a 'spaceStep' call) timestep.
+spaceCurrentTimeStep :: Space -> GettableStateVar Double
+spaceCurrentTimeStep = makeGettableStateVar . cpSpaceGetCurrentTimeStep
+
+-- | Returns true when you cannot add/remove objects from the space.
+-- In particular, spaces are locked when in a collision callback.
+-- Instead, run your code in a post-step callback instead.
+{# fun unsafe cpSpaceIsLocked as spaceIsLocked {`Space'} -> `Bool' #}
+
+{# fun unsafe cpSpaceGetUserData {`Space'} -> `DataPtr' #}
+
+{# fun unsafe cpSpaceSetUserData {`Space', `DataPtr'} -> `()' #}
+
+-- | A user definable data pointer.
+-- It is often useful to point this at the gamestate object
+-- or scene management object that owns the space.
+spaceUserData :: Space -> StateVar DataPtr
+spaceUserData = mkStateVar cpSpaceGetUserData cpSpaceSetUserData
+
+{# fun unsafe cpSpaceGetStaticBody {`Space'} -> `Body' #}
+
+-- | A dedicated static body for the space.
+-- You don’t have to use it,
+-- but because its memory is managed automatically with the space its very convenient.
+-- You can set its user data pointer to something helpful if you want for callbacks.
+spaceStaticBody :: Space -> GettableStateVar Body
+spaceStaticBody = makeGettableStateVar . cpSpaceGetStaticBody
+
+-- | Standard Chipmunk allocation function.
+{# fun unsafe cpSpaceNew as spaceNew {} -> `Space' #}
+
+-- | Standard Chipmunk deallocation function.
+{# fun cpSpaceFree as spaceFree {`Space'} -> `()' #}
+-- no "unsafe" qualifier because I think it may trigger separte callbacks
+
+-- | Add shape to the space.
+{# fun unsafe cpSpaceAddShape as spaceAddShape {`Space', `Shape'} -> `()' #}
+
+-- | Add body to the space.
+{# fun unsafe cpSpaceAddBody as spaceAddBody {`Space', `Body'} -> `()' #}
+
+-- | Add constraint to the space.
+{# fun unsafe cpSpaceAddConstraint as spaceAddConstraint {`Space', `Constraint'} -> `()' #}
+
+-- | Remove shape from the space.
+{# fun cpSpaceRemoveShape as spaceRemoveShape {`Space', `Shape'} -> `()' #}
+-- no "unsafe" qualifier because I think it may trigger separte callbacks
+
+-- | Remove body from the space.
+{# fun cpSpaceRemoveBody as spaceRemoveBody {`Space', `Body'} -> `()' #}
+-- no "unsafe" qualifier because I think it may trigger separte callbacks
+
+-- | Remove constraint from the space.
+{# fun cpSpaceRemoveConstraint as spaceRemoveConstraint {`Space', `Constraint'} -> `()' #}
+-- no "unsafe" qualifier because I think it may trigger separte callbacks
+
+-- | Check if shape is attached to the space.
+{# fun unsafe cpSpaceContainsShape as spaceContainsShape {`Space', `Shape'} -> `Bool' #}
+
+-- | Check if body is attached to the space.
+{# fun unsafe cpSpaceContainsBody as spaceContainsBody {`Space', `Body'} -> `Bool' #}
+
+-- | Check if constraint is attached to the space.
+{# fun unsafe cpSpaceContainsConstraint as spaceContainsConstraint {`Space', `Constraint'} -> `Bool' #}
+
+-- | Reindex a specific shape.
+{# fun unsafe cpSpaceReindexShape as spaceReindexShape {`Space', `Shape'} -> `()' #}
+
+-- | Reindex all the shapes for a certain body.
+{# fun unsafe cpSpaceReindexShapesForBody as spaceReindexShapesForBody {`Space', `Body'} -> `()' #}
+
+-- | Reindex all static shapes. Generally updating only the shapes that changed is faster.
+{# fun unsafe cpSpaceReindexStatic as spaceReindexStatic {`Space'} -> `()' #}
+
+-- | Type of callback which can be used to iterate all 'Body's in a 'Space'.
+type SpaceBodyIteratorFunc = Body -> Ptr () -> IO ()
+
+foreign import ccall unsafe "wrapper"
+  mkSpaceBodyIteratorFunc :: SpaceBodyIteratorFunc -> IO (FunPtr SpaceBodyIteratorFunc)
+
+-- | Call @func@ for each body in the @space@ also passing along your @data@ pointer.
+-- Sleeping bodies are included, but static and kinematic bodies are not as they aren’t added to the space.
+{# fun cpSpaceEachBody as spaceEachBody
+  { `Space'                               -- ^ space
+  , withIterator* `SpaceBodyIteratorFunc' -- ^ func
+  , `Ptr ()'                              -- ^ data
+  } -> `()' #}
+  where
+    withIterator i = mkSpaceBodyIteratorFunc i `bracket` freeHaskellFunPtr
+
+-- | Type of callback which can be used to iterate all 'Shape's in a 'Space'.
+type SpaceShapeIteratorFunc = Shape -> Ptr () -> IO ()
+
+foreign import ccall unsafe "wrapper"
+  mkSpaceShapeIteratorFunc :: SpaceShapeIteratorFunc -> IO (FunPtr SpaceShapeIteratorFunc)
+
+-- | Call @func@ for each shape in the @space@ also passing along your @data@ pointer.
+-- Sleeping and static shapes are included.
+{# fun cpSpaceEachShape as spaceEachShape
+  { `Space'                                -- ^ space
+  , withIterator* `SpaceShapeIteratorFunc' -- ^ func
+  , `Ptr ()'                               -- ^ data
+  } -> `()' #}
+  where
+    withIterator i = mkSpaceShapeIteratorFunc i `bracket` freeHaskellFunPtr
+
+-- | Type of callback which can be used to iterate all 'Constraint's in a 'Space'.
+type SpaceConstraintIteratorFunc = Constraint -> Ptr () -> IO ()
+
+foreign import ccall unsafe "wrapper"
+  mkSpaceConstraintIteratorFunc :: SpaceConstraintIteratorFunc -> IO (FunPtr SpaceConstraintIteratorFunc)
+
+-- | Call func for each constraint in the space also passing along your data pointer.
+{# fun cpSpaceEachConstraint as spaceEachConstraint
+  { `Space'                                     -- ^ space
+  , withIterator* `SpaceConstraintIteratorFunc' -- ^ func
+  , `Ptr ()'                                    -- ^ data
+  } -> `()' #}
+  where
+    withIterator i = mkSpaceConstraintIteratorFunc i `bracket` freeHaskellFunPtr
+
+-- | Update the space for the given time step. Using a fixed time step is highly recommended.
+-- Doing so can greatly increase the quality of the simulation.
+-- The easiest way to do constant timesteps is to simple step forward by 1/60th of a second
+-- (or whatever your target framerate is) for each frame regardless of how long it took to render.
+-- This works fine for many games, but a better way to do it is to separate your physics timestep and rendering.
+{# fun cpSpaceStep as spaceStep {`Space', `Double'} -> `()' #}
diff --git a/src/Chiphunk/Low/Types.chs b/src/Chiphunk/Low/Types.chs
new file mode 100644
--- /dev/null
+++ b/src/Chiphunk/Low/Types.chs
@@ -0,0 +1,224 @@
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE TypeFamilies #-}
+
+-- | Description: Basic Chipmunk data types.
+-- Module provides basic Chipmunk data types.
+module Chiphunk.Low.Types
+  ( Vect (..)
+  , VectPtr
+  , BB (..)
+  , BBPtr
+  , DataPtr
+  , Body (..)
+  , BodyType (..)
+  , Space (..)
+  , Shape (..)
+  , Constraint (..)
+  , Arbiter (..)
+  , Transform (..)
+  , TransformPtr
+  , CollisionType
+  , CPBool
+  , mkStateVar
+  ) where
+
+import Data.Cross
+import Data.StateVar
+import Data.VectorSpace
+import Foreign
+
+#include <chipmunk/chipmunk.h>
+
+-- | 2D vector packed into a struct.
+data Vect = Vect
+  { vX :: !Double, vY :: !Double
+  } deriving (Eq, Show)
+
+instance AdditiveGroup Vect where
+  zeroV = Vect 0 0
+  negateV (Vect x y) = Vect (-x) (-y)
+  Vect x1 y1 ^+^ Vect x2 y2 = Vect (x1 + x2) (y1 + y2)
+  Vect x1 y1 ^-^ Vect x2 y2 = Vect (x1 - x2) (y1 - y2)
+
+instance VectorSpace Vect where
+  type Scalar Vect = Double
+  f *^ Vect x y = Vect (f * x) (f * y)
+
+instance InnerSpace Vect where
+  Vect x1 y1 <.> Vect x2 y2 = x1 * x2 + y1 * y2
+
+instance HasCross2 Vect where
+  cross2 (Vect x y) = Vect (-y) x
+
+instance Storable Vect where
+  sizeOf _    = {# sizeof cpVect #}
+  alignment _ = {# alignof cpVect #}
+  poke p (Vect x y) = do
+    {# set cpVect->x #} p $ realToFrac x
+    {# set cpVect->y #} p $ realToFrac y
+  peek p = Vect <$> (realToFrac <$> {# get cpVect->x #} p)
+                <*> (realToFrac <$> {# get cpVect->y #} p)
+
+-- | Pointer to vector.
+{# pointer *cpVect as VectPtr -> Vect #}
+
+-- | Simple bounding box struct. Stored as left, bottom, right, top values.
+data BB = BB
+  { bbL :: !Double, bbB :: !Double, bbR :: !Double, bbT :: !Double
+  } deriving (Show)
+
+instance Storable BB where
+  sizeOf _    = {# sizeof cpBB #}
+  alignment _ = {# alignof cpBB #}
+  poke p (BB l b r t) = do
+    {# set cpBB->l #} p $ realToFrac l
+    {# set cpBB->b #} p $ realToFrac b
+    {# set cpBB->r #} p $ realToFrac r
+    {# set cpBB->t #} p $ realToFrac t
+  peek p = BB <$> (realToFrac <$> {# get cpBB->l #} p)
+              <*> (realToFrac <$> {# get cpBB->b #} p)
+              <*> (realToFrac <$> {# get cpBB->r #} p)
+              <*> (realToFrac <$> {# get cpBB->t #} p)
+
+-- | Pointer to bounding box.
+{# pointer *cpBB as BBPtr -> BB #}
+
+-- | Pointer to user data.
+{# pointer cpDataPointer as DataPtr #}
+
+-- | Rigid body somewhere in C code.
+{# pointer *cpBody as Body newtype #}
+
+instance Storable Body where
+  sizeOf (Body p)    = sizeOf p
+  alignment (Body p) = alignment p
+  poke p (Body b)    = poke (castPtr p) b
+  peek p             = Body <$> peek (castPtr p)
+
+-- | Chipmunk supports three different types of bodies with unique behavioral and performance characteristics.
+data BodyType =
+    BodyTypeDynamic
+    -- ^ Dynamic bodies are the default body type.
+    -- They react to collisions, are affected by forces and gravity, and have a finite amount of mass.
+    -- These are the type of bodies that you want the physics engine to simulate for you.
+    -- Dynamic bodies interact with all types of bodies and can generate collision callbacks.
+  | BodyTypeKimenatic
+    -- ^ Kinematic bodies are bodies that are controlled from your code instead of inside the physics engine.
+    -- They arent affected by gravity
+    -- and they have an infinite amount of mass so they don’t react to collisions or forces with other bodies.
+    -- Kinematic bodies are controlled by setting their velocity, which will cause them to move.
+    -- Good examples of kinematic bodies might include things like moving platforms.
+    -- Objects that are touching or jointed to a kinematic body are never allowed to fall asleep.
+  | BodyTypeStatic
+    -- ^ Static bodies are bodies that never (or rarely) move.
+    -- Using static bodies for things like terrain offers a big performance boost over other body types —
+    -- because Chipmunk doesn’t need to check for collisions between static objects
+    -- and it never needs to update their collision information.
+    -- Additionally, because static bodies don’t move,
+    -- Chipmunk knows it’s safe to let objects that are touching or jointed to them fall asleep.
+    -- Generally all of your level geometry will be attached to a static body
+    -- except for things like moving platforms or doors.
+    -- Every space provide a built-in static body for your convenience.
+    -- Static bodies can be moved, but there is a performance penalty as the collision information is recalculated.
+    -- There is no penalty for having multiple static bodies, and it can be useful for simplifying your code
+    -- by allowing different parts of your static geometry to be initialized or moved separately.
+
+{# enum cpBodyType as BodyType nocode
+  { CP_BODY_TYPE_DYNAMIC as BodyTypeDynamic
+  , CP_BODY_TYPE_KINEMATIC as BodyTypeKimenatic
+  , CP_BODY_TYPE_STATIC as BodyTypeStatic
+  } #}
+
+deriving instance Show BodyType
+
+-- | Spaces in Chipmunk are the basic unit of simulation. You add rigid bodies, shapes, and constraints to the space
+-- and then step them all forward through time together.
+{# pointer *cpSpace as Space newtype #}
+
+instance Storable Space where
+  sizeOf (Space p)    = sizeOf p
+  alignment (Space p) = alignment p
+  poke p (Space b)    = poke (castPtr p) b
+  peek p              = Space <$> peek (castPtr p)
+
+-- | There are currently 3 collision shape types:
+--
+-- * __Circles__: Fastest and simplest collision shape.
+--
+-- * __Line segments__: Meant mainly as a static shape. Can be beveled in order to give them a thickness.
+--
+-- * __Convex polygons__: Slowest, but most flexible collision shape.
+--
+-- You can add as many shapes to a body as you wish. That is why the two types are separate.
+--
+-- Combining multiple shapes gives you the flexibility to make any object you want
+-- as well as providing different areas of the same object with different friction, elasticity or callback values.
+{# pointer *cpShape as Shape newtype #}
+
+instance Storable Shape where
+  sizeOf (Shape p)    = sizeOf p
+  alignment (Shape p) = alignment p
+  poke p (Shape b)    = poke (castPtr p) b
+  peek p              = Shape <$> peek (castPtr p)
+
+-- | A constraint is something that describes how two bodies interact with each other. (how they constrain each other)
+-- Constraints can be simple joints that allow bodies to pivot around each other like the bones in your body,
+-- or they can be more abstract like the gear joint or motors.
+{# pointer *cpConstraint as Constraint newtype #}
+
+instance Storable Constraint where
+  sizeOf (Constraint p)    = sizeOf p
+  alignment (Constraint p) = alignment p
+  poke p (Constraint b)    = poke (castPtr p) b
+  peek p                   = Constraint <$> peek (castPtr p)
+
+-- | Chipmunk’s 'Arbiter' struct encapsulates a pair of colliding shapes and all of the data about their collision.
+-- 'Arbiter' is created when a collision starts, and persist until those shapes are no longer colliding.
+--
+-- Why are they called arbiters? The short answer is that I kept using the word “arbitrates”
+-- to describe the way that collisions were resolved and then I saw that Box2D actually called them arbiters
+-- way back in 2006 when I was looking at its solver.
+-- An arbiter is like a judge, a person that has authority to settle disputes between two people.
+-- It was a fun, fitting name and was shorter to type than CollisionPair which I had been using.
+-- It was originally meant to be a private internal structure only, but evolved to be useful from callbacks.
+{# pointer *cpArbiter as Arbiter newtype #}
+
+instance Storable Arbiter where
+  sizeOf (Arbiter p)    = sizeOf p
+  alignment (Arbiter p) = alignment p
+  poke p (Arbiter b)    = poke (castPtr p) b
+  peek p                = Arbiter <$> peek (castPtr p)
+
+-- | Type used for 2×3 affine transforms in Chipmunk.
+data Transform = Transform
+  { tA :: !Double, tB :: !Double, tC :: !Double, tD :: !Double, tTx :: !Double, tTy :: !Double
+  } deriving Show
+
+instance Storable Transform where
+  sizeOf _    = {# sizeof cpTransform #}
+  alignment _ = {# alignof cpTransform #}
+  poke p (Transform a b c d tx ty) = do
+    {# set cpTransform->a #} p  $ realToFrac a
+    {# set cpTransform->b #} p  $ realToFrac b
+    {# set cpTransform->c #} p  $ realToFrac c
+    {# set cpTransform->d #} p  $ realToFrac d
+    {# set cpTransform->tx #} p $ realToFrac tx
+    {# set cpTransform->ty #} p $ realToFrac ty
+  peek p = Transform <$> (realToFrac <$> {# get cpTransform->a #} p)
+                     <*> (realToFrac <$> {# get cpTransform->b #} p)
+                     <*> (realToFrac <$> {# get cpTransform->c #} p)
+                     <*> (realToFrac <$> {# get cpTransform->d #} p)
+                     <*> (realToFrac <$> {# get cpTransform->tx #} p)
+                     <*> (realToFrac <$> {# get cpTransform->ty #} p)
+
+-- | Pointer to 'Transform'
+{# pointer *cpTransform as TransformPtr -> Transform #}
+
+-- | Collision type
+type CollisionType = WordPtr
+
+type CPBool = {# type cpBool #}
+
+-- | 'makeStateVar' lifted to reader monad
+mkStateVar :: (a -> IO b) -> (a -> b -> IO ()) -> a -> StateVar b
+mkStateVar g s i = makeStateVar (g i) (s i)
diff --git a/src/Chiphunk/Low/Vect.chs b/src/Chiphunk/Low/Vect.chs
new file mode 100644
--- /dev/null
+++ b/src/Chiphunk/Low/Vect.chs
@@ -0,0 +1,219 @@
+-- | Description: 2D vector manipulations.
+-- Module provides utilities to manipulate 2D vectors. Most of the code is re-implemented in Haskell (mirrorring C)
+-- to avoid unnecessary foreign calls/marshalling, but only for simple operations.
+--
+-- Also note that 'Vect' has 'Eq', 'AdditiveGroup', 'VectorSpace', 'InnerSpace' and 'HasCross2' instances.
+-- Large part of functions in this module just provides Chiphunk-compatible aliases for those instances' methods.
+module Chiphunk.Low.Vect
+  ( Vect (..)
+  , cpv
+  , vZero
+  , vEql
+  , vAdd
+  , vSub
+  , vNeg
+  , vMult
+  , vDot
+  , vCross
+  , vPerp
+  , vRPerp
+  , vProject
+  , vRotate
+  , vUnRotate
+  , vLength
+  , vLengthSq
+  , vLerp
+  , vLerpConst
+  , vSLerp
+  , vSLerpConst
+  , vNormalize
+  , vClamp
+  , vDist
+  , vDistSq
+  , vNear
+  , vForAngle
+  , vToAngle
+  ) where
+
+import Data.Cross
+import Data.VectorSpace
+import Foreign
+
+{# import Chiphunk.Low.Types #}
+
+#include <wrapper.h>
+
+-- | Convenience constructor for creating new cpVect structs.
+-- Alias for 'Vect'
+cpv :: Double -> Double -> Vect
+cpv = Vect
+
+-- | Constant for the zero vector.
+--
+-- Alias for 'zeroV'
+vZero :: Vect
+vZero = zeroV
+
+-- | Check if two vectors are equal. (Be careful when comparing floating point numbers!)
+--
+-- Alias for '=='.
+vEql :: Vect -> Vect -> Bool
+vEql = (==)
+
+-- | Add two vectors.
+--
+-- Alias for '^+^'.
+vAdd :: Vect -> Vect -> Vect
+vAdd = (^+^)
+
+-- | Subtract two vectors.
+--
+-- Alias for '^-^'.
+vSub :: Vect -> Vect -> Vect
+vSub = (^-^)
+
+-- | Negate a vector.
+--
+-- Alias for 'negateV'.
+vNeg :: Vect -> Vect
+vNeg = negateV
+
+-- | Scalar multiplication.
+--
+-- Alias for '^*'.
+vMult :: Vect -> Double -> Vect
+vMult = (^*)
+
+-- | Vector dot product.
+--
+-- Alias for '<.>'.
+vDot :: Vect -> Vect -> Double
+vDot = (<.>)
+
+-- | 2D vector cross product analog. The cross product of 2D vectors results in a 3D vector with only a z component.
+-- This function returns the value along the z-axis.
+vCross :: Vect -> Vect -> Double
+Vect x1 y1 `vCross` Vect x2 y2 = x1 * y2 - y1 * x2
+
+-- | Returns a perpendicular vector. (90 degree rotation)
+--
+-- Alias for 'cross2'.
+vPerp :: Vect -> Vect
+vPerp = cross2
+
+-- | Returns a perpendicular vector. (-90 degree rotation)
+vRPerp :: Vect -> Vect
+vRPerp v = negateV $ cross2 v
+
+-- | Returns the vector projection of @v1@ onto @v2@.
+--
+-- Alias for 'project'.
+vProject
+  :: Vect -- ^ v1
+  -> Vect -- ^ v2
+  -> Vect
+vProject = project
+
+-- | Uses complex multiplication to rotate @v1@ by @v2@. Scaling will occur if @v1@ is not a unit vector.
+vRotate
+  :: Vect -- ^ v1
+  -> Vect -- ^ v2
+  -> Vect
+Vect x1 y1 `vRotate` Vect x2 y2 = Vect (x1 * x2 - y1 * y2) (x1 * y2 + x2 * y1)
+
+-- | Inverse of 'vRotate'.
+vUnRotate :: Vect -> Vect -> Vect
+Vect x1 y1 `vUnRotate` Vect x2 y2 = Vect (x1 * x2 + y1 * y2) (x2 * y1 - x1 * y2)
+
+-- | Returns the length of v.
+--
+-- Alias for 'magnitude'.
+vLength :: Vect -> Double
+vLength = magnitude
+
+-- | Returns the squared length of @v@. Faster than 'vLength' when you only need to compare lengths.
+--
+-- Alias for 'magnitudeSq'.
+vLengthSq :: Vect -> Double
+vLengthSq = magnitudeSq
+
+-- | Linearly interpolate between @v1@ and @v2@.
+--
+-- Alias for 'lerp'.
+vLerp
+  :: Vect   -- ^ v1
+  -> Vect   -- ^ v2
+  -> Double
+  -> Vect
+vLerp = lerp
+
+-- | Linearly interpolate between @v1@ towards @v2@ by distance @d@.
+vLerpConst
+  :: Vect   -- ^ v1
+  -> Vect   -- ^ v2
+  -> Double -- ^ d
+  -> Vect
+vLerpConst a b l = a ^+^ vClamp (b ^-^ a) l
+
+-- | Spherical linearly interpolate between v1 and v2.
+{# fun pure unsafe w_cpvslerp as vSLerp
+  { with* %`Vect'        -- ^ v1
+  , with* %`Vect'        -- ^ v2
+  , `Double'
+  , alloca- `Vect' peek*
+  } -> `()' #}
+
+-- | Spherical linearly interpolate between @v1@ towards @v2@ by no more than angle @a@ in radians.
+{# fun pure unsafe w_cpvslerpconst as vSLerpConst
+  { with* %`Vect'        -- ^ v1
+  , with* %`Vect'        -- ^ v2
+  , `Double'             -- ^ a
+  , alloca- `Vect' peek*
+  } -> `()' #}
+
+-- | Returns a normalized copy of @v@. As a special case, it returns 'vZero' when called on 'vZero'.
+--
+-- Alias for 'normalized'.
+vNormalize :: Vect -> Vect
+vNormalize = normalized
+
+-- | Clamp @v@ to length @len@.
+vClamp
+  :: Vect   -- ^ v
+  -> Double -- ^ len
+  -> Vect
+vClamp v l
+  | magnitudeSq v > l * l = l *^ normalized v
+  | otherwise             = v
+
+-- | Returns the distance between @v1@ and @v2@.
+vDist
+  :: Vect   -- ^ v1
+  -> Vect   -- ^ v2
+  -> Double
+vDist v1 v2 = magnitude $ v1 ^-^ v2
+
+-- | Returns the squared distance between @v1@ and @v2@. Faster than 'vDist' when you only need to compare distances.
+vDistSq
+  :: Vect   -- ^ v1
+  -> Vect   -- ^ v2
+  -> Double
+vDistSq v1 v2 = magnitudeSq $ v1 ^-^ v2
+
+-- | Returns true if the distance between @v1@ and @v2@ is less than @dist@.
+vNear
+  :: Vect   -- ^ v1
+  -> Vect   -- ^ v2
+  -> Double -- ^ dist
+  -> Bool
+vNear v1 v2 d = vDistSq v1 v2 < d * d
+
+-- | Returns the unit length vector for the given angle (in radians).
+vForAngle :: Double -> Vect
+vForAngle alpha = Vect (cos alpha) (sin alpha)
+
+-- | Returns the angular direction @v@ is pointing in (in radians).
+vToAngle
+  :: Vect   -- ^ v
+  -> Double
+vToAngle (Vect x y) = atan2 y x
diff --git a/src/Chiphunk/wrapper.c b/src/Chiphunk/wrapper.c
new file mode 100644
--- /dev/null
+++ b/src/Chiphunk/wrapper.c
@@ -0,0 +1,176 @@
+#include <wrapper.h>
+
+void w_cpvslerp(cpVect v1, cpVect v2, cpFloat t, cpVect *out)
+{
+  *out = cpvslerp(v1, v2, t);
+}
+
+void w_cpvslerpconst(cpVect v1, cpVect v2, cpFloat a, cpVect *out)
+{
+  *out = cpvslerpconst(v1, v2, a);
+}
+
+void w_cpBodyGetPosition(const cpBody *body, cpVect *out)
+{
+  *out = cpBodyGetPosition(body);
+}
+
+void w_cpBodyGetCenterOfGravity(const cpBody *body, cpVect *out)
+{
+  *out = cpBodyGetCenterOfGravity(body);
+}
+
+void w_cpBodyGetVelocity(const cpBody *body, cpVect *out)
+{
+  *out = cpBodyGetVelocity(body);
+}
+
+void w_cpBodyGetForce(const cpBody *body, cpVect *out)
+{
+  *out = cpBodyGetForce(body);
+}
+
+void w_cpBodyGetRotation(const cpBody *body, cpVect *out)
+{
+  *out = cpBodyGetRotation(body);
+}
+
+void w_cpBodyLocalToWorld(const cpBody *body, cpVect point, cpVect *out)
+{
+  *out = cpBodyLocalToWorld(body, point);
+}
+
+void w_cpBodyWorldToLocal(const cpBody *body, cpVect point, cpVect *out)
+{
+  *out = cpBodyWorldToLocal(body, point);
+}
+
+void w_cpBodyGetVelocityAtWorldPoint(const cpBody *body, cpVect point, cpVect *out)
+{
+  *out = cpBodyGetVelocityAtWorldPoint(body, point);
+}
+
+void w_cpBodyGetVelocityAtLocalPoint(const cpBody *body, cpVect point, cpVect *out)
+{
+  *out = cpBodyGetVelocityAtLocalPoint(body, point);
+}
+
+void w_cpShapeGetBB(const cpShape *shape, cpBB *out)
+{
+  *out = cpShapeGetBB(shape);
+}
+
+void w_cpShapeGetSurfaceVelocity(const cpShape *shape, cpVect *out)
+{
+  *out = cpShapeGetSurfaceVelocity(shape);
+}
+
+void w_cpShapeGetFilter(const cpShape *shape, cpShapeFilter *out)
+{
+  *out = cpShapeGetFilter(shape);
+}
+
+void w_cpShapeCacheBB(cpShape *shape, cpBB *out)
+{
+  *out = cpShapeCacheBB(shape);
+}
+
+void w_cpShapeUpdate(cpShape *shape, cpTransform transform, cpBB *out)
+{
+  *out = cpShapeUpdate(shape, transform);
+}
+
+void w_cpCentroidForPoly(int count, const cpVect *vects, cpVect *out)
+{
+  *out = cpCentroidForPoly(count, vects);
+}
+
+cpFloat w_cpBBSegmentQuery(cpBB bb, cpVect a, cpVect b)
+{
+  return cpBBSegmentQuery(bb, a, b);
+}
+
+cpBool w_cpBBIntersectsSegment(cpBB bb, cpVect a, cpVect b)
+{
+  return cpBBIntersectsSegment(bb, a, b);
+}
+
+void w_cpSpaceGetGravity(cpSpace *space, cpVect *out)
+{
+  *out = cpSpaceGetGravity(space);
+}
+
+void w_cpPinJointGetAnchorA(const cpConstraint *constraint, cpVect *out)
+{
+  *out = cpPinJointGetAnchorA(constraint);
+}
+
+void w_cpPinJointGetAnchorB(const cpConstraint *constraint, cpVect *out)
+{
+  *out = cpPinJointGetAnchorB(constraint);
+}
+
+void w_cpSlideJointGetAnchorA(const cpConstraint *constraint, cpVect *out)
+{
+  *out = cpSlideJointGetAnchorA(constraint);
+}
+
+void w_cpSlideJointGetAnchorB(const cpConstraint *constraint, cpVect *out)
+{
+  *out = cpSlideJointGetAnchorB(constraint);
+}
+
+void w_cpPivotJointGetAnchorA(const cpConstraint *constraint, cpVect *out)
+{
+  *out = cpPivotJointGetAnchorA(constraint);
+}
+
+void w_cpPivotJointGetAnchorB(const cpConstraint *constraint, cpVect *out)
+{
+  *out = cpPivotJointGetAnchorB(constraint);
+}
+
+void w_cpGrooveJointGetGrooveA(const cpConstraint *constraint, cpVect *out)
+{
+  *out = cpGrooveJointGetGrooveA(constraint);
+}
+
+void w_cpGrooveJointGetGrooveB(const cpConstraint *constraint, cpVect *out)
+{
+  *out = cpGrooveJointGetGrooveB(constraint);
+}
+
+void w_cpGrooveJointGetAnchorB(const cpConstraint *constraint, cpVect *out)
+{
+  *out = cpGrooveJointGetAnchorB(constraint);
+}
+
+void w_cpDampedSpringGetAnchorA(const cpConstraint *constraint, cpVect *out)
+{
+  *out = cpDampedSpringGetAnchorA(constraint);
+}
+
+void w_cpDampedSpringGetAnchorB(const cpConstraint *constraint, cpVect *out)
+{
+  *out = cpDampedSpringGetAnchorB(constraint);
+}
+
+void w_cpArbiterGetSurfaceVelocity(cpArbiter *arbiter, cpVect *out)
+{
+  *out = cpArbiterGetSurfaceVelocity(arbiter);
+}
+
+void w_cpArbiterGetNormal(const cpArbiter *arbiter, cpVect *out)
+{
+  *out = cpArbiterGetNormal(arbiter);
+}
+
+void w_cpArbiterGetPointA(const cpArbiter *arbiter, int i, cpVect *out)
+{
+  *out = cpArbiterGetPointA(arbiter, i);
+}
+
+void w_cpArbiterGetPointB(const cpArbiter *arbiter, int i, cpVect *out)
+{
+  *out = cpArbiterGetPointB(arbiter, i);
+}
