[Add] Support for FreeBSD. Had to play around with the physics slightly

as FreeBSD didn't like the optimizations in Runge-Kuta forcing it to
eventually become NaN.
This commit is contained in:
Allanis 2014-04-10 01:07:20 +01:00
parent 2809e5323f
commit a17b7792f3
6 changed files with 109 additions and 57 deletions

View File

@ -3,6 +3,7 @@ DEBUG := 1
#DEBUG_PARANOID := 1 #DEBUG_PARANOID := 1
OS := LINUX OS := LINUX
#OS := FREEBSD
#OS := WIN32 #OS := WIN32
#OS := MACOS #OS := MACOS
export OS export OS
@ -36,10 +37,17 @@ CFLAGS += -DDATA_DEF=$(DATA_DEF)
endif endif
# OS Stuff. # OS Stuff.
# Linux Stuff.
ifeq ($(OS),LINUX) ifeq ($(OS),LINUX)
CFLAGS += -D_POSIX_SOURCE CFLAGS += -D_POSIX_SOURCE
endif endif
# FreeBSD stuff.
ifeq ($(OS),FREEBSD)
CFLAGS += -D_POSIX_SOURCE -D__BSD_VISIBLE
endif
# Debug stuff. # Debug stuff.
ifdef DEBUG ifdef DEBUG
CFLAGS += -W -Wall -Wextra -Wunused -Wshadow -Wpointer-arith -Wmissing-prototypes \ CFLAGS += -W -Wall -Wextra -Wunused -Wshadow -Wpointer-arith -Wmissing-prototypes \
@ -51,10 +59,17 @@ CFLAGS += -DDEBUG_PARANOID
endif endif
# Handle OS Debug stuff here. # Handle OS Debug stuff here.
# Linux Stuff.
ifeq ($(OS), LINUX) ifeq ($(OS), LINUX)
LDFLAGS += -rdynamic LDFLAGS += -rdynamic
endif # Linux. endif # Linux.
# FreeBSD stuff.
ifeq ($(OS), FREEBSD)
LDFLAGS += -rdynamic
endif
else # DEBUG else # DEBUG
CFLAGS += -O2 -funroll-loops -pipe -std=c99 CFLAGS += -O2 -funroll-loops -pipe -std=c99
endif endif

View File

@ -729,12 +729,10 @@ static const char* debug_sigCodeToStr(int sig, int sig_code) {
case SEGV_ACCERR: return "SIGEGV (invalid permissions for mapped object)"; case SEGV_ACCERR: return "SIGEGV (invalid permissions for mapped object)";
default: return "SIGSEGV"; default: return "SIGSEGV";
} }
else if(sig == SIGTRAP) else if(sig == SIGABRT)
switch(sig_code) { switch(sig_code) {
case SI_USER: return "SIGTRAP (raised by program)"; case SI_USER: return "SIGABRT (raised by program)";
case TRAP_BRKPT: return "SIGTRAP (process breakpoint)"; default: return "SIGABRT";
case TRAP_TRACE: return "SIGTRAP (process trace trap)";
default: return "SIGTRAP";
} }
/* No suitable code found. */ /* No suitable code found. */
return strsignal(sig); return strsignal(sig);
@ -786,9 +784,9 @@ static void debug_sigInit(void) {
sigaction(SIGFPE, &sa, &so); sigaction(SIGFPE, &sa, &so);
if(so.sa_handler == SIG_IGN) if(so.sa_handler == SIG_IGN)
DEBUG("Unable to set up SIGFPE signal handler."); DEBUG("Unable to set up SIGFPE signal handler.");
sigaction(SIGTRAP, &sa, &so); sigaction(SIGABRT, &sa, &so);
if(so.sa_handler == SIG_IGN) if(so.sa_handler == SIG_IGN)
DEBUG("Unable to get set up SIGTRAP signal handler."); DEBUG("Unable to get set up SIGABRT signal handler.");
#endif /* #if defined(LINUX) && !defined(NODEBUG) */ #endif /* #if defined(LINUX) && !defined(NODEBUG) */
} }

View File

@ -9,7 +9,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
#ifdef LINUX #if defined(LINUX) || defined(FREEBSD)
#include <stdlib.h> #include <stdlib.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -33,7 +33,7 @@ char* lfile_basePath(void) {
char* home; char* home;
if(lephisto_base[0] == '\0') { if(lephisto_base[0] == '\0') {
#ifdef LINUX #if defined(LINUX) || defined(FREEBSD)
home = getenv("HOME"); home = getenv("HOME");
snprintf(lephisto_base, PATH_MAX, "%s/.lephisto/", home); snprintf(lephisto_base, PATH_MAX, "%s/.lephisto/", home);
#else #else
@ -71,7 +71,7 @@ int lfile_dirMakeExist(const char* path, ...) {
va_end(ap); va_end(ap);
} }
#ifdef LINUX #if defined(LINUX) || defined(FREEBSD)
struct stat buf; struct stat buf;
stat(file, &buf); stat(file, &buf);
@ -105,7 +105,7 @@ int lfile_fileExists(const char* path, ...) {
va_end(ap); va_end(ap);
} }
#ifdef LINUX #if defined(LINUX) || defined(FREEBSD)
struct stat buf; struct stat buf;
if(stat(file, &buf)==0) /* Stat worked, file must exist. */ if(stat(file, &buf)==0) /* Stat worked, file must exist. */
@ -140,7 +140,7 @@ char** lfile_readDir(int* lfiles, const char* path, ...) {
va_end(ap); va_end(ap);
} }
#ifdef LINUX #if defined(LINUX) || defined(FREEBSD)
int i, j, k, n; int i, j, k, n;
DIR* d; DIR* d;
struct dirent *dir; struct dirent *dir;

View File

@ -5,13 +5,13 @@
#define LOG(str, args...)(fprintf(stdout, str"\n", ## args)) #define LOG(str, args...)(fprintf(stdout, str"\n", ## args))
#ifdef DEBUG_PARANOID /* Will cause WARN's to blow up. */ #ifdef DEBUG_PARANOID /* Will cause WARN's to blow up. */
#define WARN(str, args...)(fprintf(stderr, "Warning: [%s] "str"\n", __func__, ## args), \ #define WARN(str, args...)(fprintf(stderr, "Warning: [%s] "str"\n", __func__, ## args), \
raise(SIGRAP)) abort())
#else #else
#define WARN(str, args...)(fprintf(stderr, "Warning: [%s] "str"\n", __func__, ## args)) #define WARN(str, args...)(fprintf(stderr, "Warning: [%s] "str"\n", __func__, ## args))
#endif #endif
#define ERR(str, args...) (fprintf(stderr, "ERROR %s:%d: [%s] "str"\n", \ #define ERR(str, args...) (fprintf(stderr, "ERROR %s:%d: [%s] "str"\n", \
__FILE__, __LINE__, __func__, ## args), raise(SIGTRAP)) __FILE__, __LINE__, __func__, ## args), abort())
#ifdef DEBUG #ifdef DEBUG
# undef DEBUG # undef DEBUG

View File

@ -96,37 +96,46 @@ double vect_dot(Vec2* a, Vec2* b) {
return a->x * b->x + a->y * b->y; return a->x * b->x + a->y * b->y;
} }
/* ================ */ /* ================
/* SOLID! */ * SOLID!
/* ================ */ * ================
*/
/* ==Update method.======================================== */ /* ==Update method.========================================
/* d^2 x(t) / d t^2 = a, a = constant (acceleration) */ * @fn static void simple_update(Solid* obj, const double dt)
/* x'(0) = v, x(0) = p */ *
/* */ * @brief Update the solids position using a euler integration.
/* d x(t) / d t = a*t + v, v = constant (initial velocity) */ *
/* x(t) = a/2*t + v*t + p, p = constant (initial position) */ * Simple method.
/* */ *
/* Since dt isn't actually differential this gives us an */ * d^2 x(t) / d t^2 = a, a = constant (acceleration)
/* error, so watch out with big values for dt. */ * x'(0) = v, x(0) = p
/* ======================================================== */ *
#if 0 /* Simply commenting this out to avoid silly warnings. */ * d x(t) / d t = a*t + v, v = constant (initial velocity)
* x(t) = a/2*t + v*t + p, p = constant (initial position)
*
* Since dt isn't actually differential this gives us an
* error, so watch out with big values for dt.
* ========================================================
*/
#if defined(FREEBSD)
static void simple_update(Solid* obj, const double dt) { static void simple_update(Solid* obj, const double dt) {
double px, py, vx, vy, ax, ay;
/* Make sure angle doesn't flip. */ /* Make sure angle doesn't flip. */
obj->dir += M_PI/360.*obj->dir_vel*dt; obj->dir += M_PI/180.*obj->dir_vel*dt;
if(obj->dir > 2*M_PI) obj->dir -= 2*M_PI; if(obj->dir > 2*M_PI) obj->dir -= 2*M_PI;
if(obj->dir < 0.) obj->dir += 2*M_PI; if(obj->dir < 0.) obj->dir += 2*M_PI;
double px, py, vx, vy; /* Initial positions. */
px = obj->pos->x; px = obj->pos.x;
py = obj->pos->y; py = obj->pos.y;
vx = obj->vel->x; vx = obj->vel.x;
vy = obj->vel->y; vy = obj->vel.y;
if(obj->force.mod) { /* Force applied on an object. */ if(obj->force.mod) { /* Force applied on an object. */
double ax, ay; ax = obj->force.x /obj->mass;
ax = obj->force->x/obj->mass; ay = obj->force.y /obj->mass;
ay = obj->force->y/obj->mass;
vx += ax*dt; vx += ax*dt;
vy += ay*dt; vy += ay*dt;
@ -140,26 +149,39 @@ static void simple_update(Solid* obj, const double dt) {
px += vx*dt; px += vx*dt;
py += vy*dt; py += vy*dt;
} }
obj->pos.mod = MOD(px, py);
obj->pos.angle = ANGLE(px, py); /* Update position and velocity. */
vect_cset(&obj->vel, vx, vy);
vect_cset(&obj->pos, px, py);
} }
#endif #endif /* defined(FREEBSD) */
/* ==Runge-Kutta 4th method.=============================== */ /* ==Runge-Kutta 4th method.===============================
/* d^2 x(t) / d t^2 = a, a = constant(acceleration) */ *
/* x'(0) = v, x(0) = p */ * @brief Runge-Kutta method of updating a solid based on it's
/* x'' = f(t, x, x') = (x', a) */ * acceleration.
/* */ *
/* x_ {n+1} = x_n + h/6 (k1 + 2*k2 + 3*k3 + k4) */ * d^2 x(t) / d t^2 = a, a = constant(acceleration)
/* h = (b-a)/2 */ * x'(0) = v, x(0) = p
/* k1 = f(t_n, X_n), X_n = (x_n, x'_n) */ * x'' = f(t, x, x') = (x', a)
/* k2 = f(t_n + h/2, X_n + h/2*k1) */ *
/* k3 = f(t_n + h/2, X_n + h/2*k2) */ * x_ {n+1} = x_n + h/6 (k1 + 2*k2 + 3*k3 + k4)
/* k4 = f(t_n + h, X_n + h*k3) */ * h = (b-a)/2
/* */ * k1 = f(t_n, X_n), X_n = (x_n, x'_n)
/* x_{n+1} = x_n + h/6x'_n + 3*h*a, 4*a) */ * k2 = f(t_n + h/2, X_n + h/2*k1)
/* ======================================================== */ * k3 = f(t_n + h/2, X_n + h/2*k2)
* k4 = f(t_n + h, X_n + h*k3)
*
* x_{n+1} = x_n + h/6x'_n + 3*h*a, 4*a)
*
* Main advantage comes thanks to the fact that Lephisto is on
* a 2D plane. Therefore RK chops it up in chunks and actually
* creates a tiny curve instead of aproximating the curve for
* a tiny staight line.
* ========================================================
*/
#if !defined(FREEBSD)
#define RK4_MIN_H 0.01 /* Minimal pass we want. */ #define RK4_MIN_H 0.01 /* Minimal pass we want. */
static void rk4_update(Solid* obj, const double dt) { static void rk4_update(Solid* obj, const double dt) {
int i, N; /* For iteration and pass calculation. */ int i, N; /* For iteration and pass calculation. */
@ -170,9 +192,11 @@ static void rk4_update(Solid* obj, const double dt) {
if(obj->dir >= 2.*M_PI) obj->dir -= 2*M_PI; if(obj->dir >= 2.*M_PI) obj->dir -= 2*M_PI;
else if(obj->dir < 0.) obj->dir += 2*M_PI; else if(obj->dir < 0.) obj->dir += 2*M_PI;
/* Initial RK parameters. */
N = (dt > RK4_MIN_H) ? (int)(dt/RK4_MIN_H) : 1; N = (dt > RK4_MIN_H) ? (int)(dt/RK4_MIN_H) : 1;
h = dt / (double)N; /* Step. */ h = dt / (double)N; /* Step. */
/* Initial positions and velocity. */
px = obj->pos.x; px = obj->pos.x;
py = obj->pos.y; py = obj->pos.y;
vx = obj->vel.x; vx = obj->vel.x;
@ -212,26 +236,41 @@ static void rk4_update(Solid* obj, const double dt) {
} }
vect_cset(&obj->pos, px, py); vect_cset(&obj->pos, px, py);
} }
#endif /* !defined(FREEBSD) */
/* Initialize a new solid. */ /* Initialize a new solid. */
void solid_init(Solid* dest, const double mass, const double dir, void solid_init(Solid* dest, const double mass, const double dir,
const Vec2* pos, const Vec2* vel) { const Vec2* pos, const Vec2* vel) {
dest->mass = mass; dest->mass = mass;
/* Set direction velocity. */
dest->dir_vel = 0.; dest->dir_vel = 0.;
vect_cset(&dest->force, 0., 0.); /* Set force. */
vectnull(&dest->force);
/* Set direction. */
dest->dir = dir; dest->dir = dir;
if((dest->dir > 2.*M_PI) || (dest->dir < 0.)) if((dest->dir > 2.*M_PI) || (dest->dir < 0.))
dest->dir = fmod(dest->dir, 2*M_PI); dest->dir = fmod(dest->dir, 2*M_PI);
/* Set velocity. */
if(vel == NULL) vectnull(&dest->vel); if(vel == NULL) vectnull(&dest->vel);
else vectcpy(&dest->vel, vel); else vectcpy(&dest->vel, vel);
/* Set position. */
if(pos == NULL) vectnull(&dest->pos); if(pos == NULL) vectnull(&dest->pos);
else vectcpy(&dest->pos, pos); else vectcpy(&dest->pos, pos);
/*
* FreeBSD seems to have a bug with optimizations in rk4_update causing it to
* eventually become NaN.
*/
#if defined(FREEBSD)
dest->update = simple_update;
#else
dest->update = rk4_update; dest->update = rk4_update;
#endif
} }
/* Create a new solid. */ /* Create a new solid. */

View File

@ -11,7 +11,7 @@
#include <unistd.h> #include <unistd.h>
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#ifdef LINUX #if defined _POSIX_SOURCE
#include <sys/time.h> #include <sys/time.h>
#include <fcntl.h> #include <fcntl.h>
#endif #endif