Donnerstag, 1. Juli 2021

Loonies 8192 now for Maemo 4 (N800) and MeeGo 1.2 Harmattan (N9)

As part of a summer clean-up of the desk drawers, I pulled out the N800 and N9 and ported my game Loonies 8192 to these devices. Since those are "proper" Linux devices, one can compile things directly on-device (just install gcc from the SDK repos), and with SSH, it's easy to type on a real keyboard.

Anyway, you can install the game via the landing pages:

For the N800, make sure "maemo Extras" is enabled so it will find libsdl1.2 if it's not already installed. Head over to https://loonies.thp.io/n800/ on the device and download the deb, it will be installed by Application manager.

For the N9, make sure you have n9repomirror installed (again, so libsdl1.2 can be installed if necessary). Enable third party applications in Settings, Applications, Installations. Then head over to https://loonies.thp.io/n9/ on the device and download the deb, selecting after the download is finished will ask you to install it.

The N9 version is also available on openrepos.net.

And don't forget that the game is also available for DOS, various consoles and handheld consoles as well as on Windows. All of the builds are available on itch.io.

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: https://openrepos.net/content/thp/rebounce

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 librebounce.so rebounce.c

LD_PRELOAD=$(pwd)/librebounce.so /opt/bounce/bin/bounce

exit 0

#endif


/**

 * 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 <m@thp.io>

 **/


#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_Init(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO);


    SDL_Joystick *accelerometer = SDL_JoystickOpen(0);


    while (1) {

        SDL_JoystickUpdate();


        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);

        fclose(out);

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


        SDL_Delay(10);

    }


    return NULL;

}


FILE *

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);

}