Donnerstag, 11. Februar 2021

reBounce - softfp-to-hardfp LD_PRELOAD hack for Bounce on N9

This depends on Bounce (the N900 .deb) and SDL 1.2 being installed. Google "bounce_1.0.0_armel.deb" for the former, and use n9repomirror for the latter.

This is available on OpenRepos:

Source code (copy'n'paste this into a file named "rebounce.c", then run it using your shell):

#if 0

gcc -Os -shared -fPIC -lSDL -o rebounce.c

LD_PRELOAD=$(pwd)/ /opt/bounce/bin/bounce

exit 0



 * reBounce -- softfp-to-hardfp LD_PRELOAD hack for Bounce on N9


 * Bounce was a really nice 2009 tech demo on the N900. This

 * makes this tech demo work on an N9 by translating the calls

 * that use floating point arguments to the hardfp ABI. It also

 * fixes input using SDL1.2 to get sensor values from sensorfw.


 * Known issues: Audio is muted on startup until mute is toggled.


 * 2021-02-11 Thomas Perl <>


#define _GNU_SOURCE

#include <stdio.h>

#include <dlfcn.h>

#include <pthread.h>

#include <SDL/SDL.h>

#define SFP __attribute__((pcs("aapcs")))

typedef unsigned int GLuint;

static void *

sensor_thread(void *user_data)



    SDL_Joystick *accelerometer = SDL_JoystickOpen(0);

    while (1) {


        float x = 0.053888f * SDL_JoystickGetAxis(accelerometer, 0);

        float y = 0.053888f * SDL_JoystickGetAxis(accelerometer, 1);

        float z = 0.053888f * SDL_JoystickGetAxis(accelerometer, 2);

        FILE *out = fopen("/dev/shm/bounce.sensor.tmp", "wb");

        fprintf(out, "%f %f %f\n", -y, x, z);


        rename("/dev/shm/bounce.sensor.tmp", "/dev/shm/bounce.sensor");



    return NULL;



fopen(const char *filename, const char *mode)


    FILE *(*fopen_orig)(const char *, const char *) = dlsym(RTLD_NEXT, "fopen");

    if (strcmp(filename, "/sys/class/i2c-adapter/i2c-3/3-001d/coord") == 0) {

        static int sensor_inited = 0;

        if (!sensor_inited) {

            sensor_inited = 1;

            pthread_t thread;

            pthread_create(&thread, NULL, sensor_thread, NULL);


        filename = "/dev/shm/bounce.sensor";


    return fopen_orig(filename, mode);


#define f_f(name) float SFP name(float x) { return ((float (*)(float))dlsym(RTLD_NEXT, #name))(x); }

#define d_d(name) double SFP name(double x) { return ((double (*)(double))dlsym(RTLD_NEXT, #name))(x); }

#define f_ff(name) float SFP name(float x, float y) { return ((float (*)(float, float))dlsym(RTLD_NEXT, #name))(x, y); }

#define d_dd(name) double SFP name(double x, double y) { return ((double (*)(double, double))dlsym(RTLD_NEXT, #name))(x, y); }

f_f(sinhf) f_f(coshf) f_f(tanhf) f_f(asinf) f_f(acosf) f_f(atanf) f_f(sinf) f_f(cosf) f_f(tanf) f_f(expf) f_f(logf)

f_f(log10f) f_f(ceilf) f_f(floorf) d_d(log) d_d(sin) f_ff(atan2f) f_ff(fmodf) d_dd(atan2) d_dd(pow) d_dd(fmod)

double SFP

frexp(double value, int *exp)


    return ((double (*)(double, int *))dlsym(RTLD_NEXT, "frexp"))(value, exp);


double SFP

ldexp(double x, int n)


    return ((double (*)(double, int))dlsym(RTLD_NEXT, "ldexp"))(x, n);


double SFP

modf(double value, double *iptr)


    return ((double (*)(double, double *))dlsym(RTLD_NEXT, "modf"))(value, iptr);


void SFP

glClearColor(float r, float g, float b, float a)


    ((void (*)(float, float, float, float))dlsym(RTLD_NEXT, "glClearColor"))(r, g, b, a);


void SFP

glUniform4f(GLuint location, float v0, float v1, float v2, float v3)


    ((void (*)(GLuint, float, float, float, float))dlsym(RTLD_NEXT, "glUniform4f"))(location, v0, v1, v2, v3);


void SFP

glUniform1f(GLuint location, float v0)


    ((void (*)(GLuint, float))dlsym(RTLD_NEXT, "glUniform1f"))(location, v0);


Keine Kommentare: