Mittwoch, 15. Oktober 2025
Dzzee 1.9.0 for N800/N810/N900/N9/Leste
Mittwoch, 15. Februar 2023
The Maemulator: Running a certain 2009 tech demo on modern Linux
Want to revisit 2009's N900 tech demo but you got rid of your old toys long ago or don't want to bother digging them out of your desk drawer? The Maemulator to the rescue! It uses QEMU user-space emulation and some LD_PRELOAD magic + other in-process trickery to get it working on any modern Linux machine that has an OpenGL driver. Add multi-sample anti-aliasing, anisotropic filtering, higher resolutions, keyboard input and various fixes, and you are all set for a few minutes of fun distraction.
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.
#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);
}
Donnerstag, 29. Januar 2015
Running Debian sid on Sailfish OS
sudo debootstrap --arch armhf --foreign sid sid
sudo tar czvf sid.tgz -C sid .
du -sh sid.tgz
# 98M sid.tgz
scp sid.tgz nemo@192.168.2.15:
To unpack the chroot tarball:
ssh nemo@192.168.2.15
devel-su
# password
mkdir sid
cd sid
tar xvf ../sid.tgz
chroot /home/nemo/sid/ /debootstrap/debootstrap --second-stage
chroot /home/nemo/sid/ apt-get clean
echo "deb http://http.debian.net/debian sid main" \
>/home/nemo/sid/etc/apt/source.list
To enter the chroot:
ssh nemo@192.168.2.15
devel-su
# password
mount --bind /proc /home/nemo/sid/proc
mount --bind /sys /home/nemo/sid/sys
mount --bind /dev /home/nemo/sid/dev
mount --bind /dev/pts /home/nemo/sid/dev/pts
cp /etc/resolv.conf /home/nemo/sid/etc/
chroot /home/nemo/sid/
apt-get update
Samstag, 19. April 2014
My N9 apps and games now self-hosted and on openrepos.net
Here's a list of my N9 apps that you can now get for free ("deb download" is as of posting this, for new versions visit the webpage or openrepos.net):
- Billboard Standby Screen (web page, deb download, openrepos.net)
- Volume+ As Camera Button (web page, deb download, openrepos.net)
- Headset Camera Button (web page, deb download, openrepos.net)
- Personal Web Server (web page, deb download, openrepos.net)
- Mustr (web page, deb download, openrepos.net)
- gPodder (web page, deb download, openrepos.net)
- qw The Game (web page, openrepos.net)
- Tennix! Redux Demo (web page, deb download, openrepos.net)
- Petals (web page, deb download, openrepos.net)
- Brain Party (web page, openrepos.net)
- Numpty Physics (web page, openrepos.net)
- Plonk (web page, openrepos.net)
- chro.mono (web page, deb download, openrepos.net)
A list of all my apps on OpenRepos.net is also available.
Please note that unless otherwise noted, do not copy the .deb files and distribute them yourself, please always link to the project webpage (the page, not the file) or the openrepos.net page - this makes sure users can always download the latest version and from a known-good source (always be careful when downloading and installing .debs from random webpages). For end users who want to stay up to date and install the packages comfortably, the Warehouse client for OpenRepos.net is recommended.
For some of these apps (not games) that are not open source yet, I plan to clean up and publish the source at some point in the future, so interested developers can have a look, add features and/or port it to new platforms.
Samstag, 15. März 2014
gPodder 4.0.0 for Sailfish OS released
If you haven't read last year's article about Python and Qt 5, now might be a good time to do so. PyOtherSide is a much more minimalistic approach to Python bindings, and - in my obviously biased opinion - works better for gluing together a QML UI with a Python backend. In fact, it lends itself to clearly splitting the frontend from the backend, and with the "asynchronous by default" design, you have to work really hard to block your UI thread with long-running Python code (or multithreaded Python code that's waiting for the GIL to be released). PyOtherSide these days is also well-documented, and some early annoyances and bugs have been fixed with recent releases in February. In combination with Qt 5 and Python 3, it works well on OS X, Blackberry 10, Linux, Sailfish OS and Windows. With Qt 5.2 having official support for Android, and a Python 3 port being available, it's only a matter of time before PyOtherSide lands on Android.
For all Sailfish OS users out there: Until the next Sailfish OS update, you might have to install some dependencies before gPodder will correctly start up, these are:
- libpython3 (the Python 3 interpreter)
- python3-base (the Python 3 standard library)
- pyotherside (the Qt 5-Python3 bindings)






