2013-04-15

RetroArch on ODROID-U2 (with hardware acceleration, yes!)

ODROID-U2

I have tried to run decent console emulation on Raspberry Pi, without success.

So I recently got my hands on an ODROID-U2 (that comes with a respectable more powerful hardware) and that can potentially carry out my console emulation and preservation dreams.

In the below pictures you can see it shily coming out of the box:

A small package to rule them all

Better use a fan if you want to overclock this little beast!


















This development board comes with 4 ARM Cortex A9 CPUs and the Mali 400 GPU (more about this later); when choosing a development board you should really pay attention to the planned shelf life, the expected community size and the GPU driver support. There's really nothing else that will matter more for you than the open source/closed source drivers.

In these regards the vendor, Hardkernel, gets my kudos as I see they are working hard to deliver the best to the community that's aggregating around ODROID (but keep in mind that it's not yet very big right now, so weaponize yourself for all cases!).

As far as I understood the driver is partly closed-source, for longer term dreams (full open source Mali400 driver) you could check out the Lima project, although nothing usable is available at time of writing.

I was expecting some geeky adventures to achieve my goal, and I wasn't disappointed. In the last few days I had to learn all my way through forums, IRC, blog posts and generally fragmented and incomplete information - but finally after a few strong machete cuts I have been able to see the light!

Do-it-yourself

I didn't want to release the result of my efforts as Debian packages or complete SD images (update: I did!), so I will provide you with a walkthrough and the necessary steps.
The reasons are:
  • possible licensing concerns, it is not fully clear to me if I am entitled to release these (for example the vendor-provided drivers);
  • releasing concerns, once you release something you should take care to mantain it;
  • philosophy: if you are using a development board you should really get in touch with all the layers to better understand how things work.

I used this blog post as starting point and also other resources here and there; in this blog post I am focusing only on SD card booting and ODROID-U2 specifically.
Although I didn't follow it originally, you might also want to read the official post about ODROID-U2 and then come back for the other steps about Xorg configuration and RetroArch.

Update 7 May 2013: I released neagix' excellent (and unofficial) Debian Wheezy for Development&Emulation (with X11 hardware acceleration). I advise to use the image as information in this post might be obsolete.

Prerequisites

In the following steps I aim to provide an aid at getting a fully functional RetroArch on ODROID-U2.

If you can use debian apt-get/aptitude and SSH you should be able to follow it. Also you might want to use Google in case of some strange error that is not covered by this tutorial.

This is not a from-scratch tutorial for complete newbies, so please don't expect so.

Update 25-April-2013: the more advanced cores will not exhibit a great performance, but you should be fine with emulation of 16bit (and less) consoles

Step 1 - booting the device


Insert the microSD in a Linux PC, then check with dmesg|tail what is the dev node. On my PC it was /dev/mmcblk0. Please take note of the root device, not the partition device (that would be /dev/mmcblk0p1 and so on).

Now download a prepared ODROID-U2 Ubuntu image and flash it to the microSD card.


wget http://www.mdrjr.net/odroid/mirror/ODROID-U2/Ubuntu/odroidu2_20121231-linaro-ubuntu-desktop-uSD.zip
7z x odroidu2_20121231-linaro-ubuntu-desktop-uSD.zip
sudo dd if=odroidu2_20121231-linaro-ubuntu-desktop-uSD.img of=/dev/mmcblk0 bs=24M

Update 14 July 2013: use instead the odroid-wheezy-retro image, instructions here

At this point I advice to eject/insert the microSD card, then run the following:

sudo resize2fs /dev/mmcblk0p2

This will resize the linux partition to the maximum available space on your SD card.

Before proceeding to next step you might want to mount the /dev/mmcblk0p2 partition and change some files there for easier initial setup (like wired network, for example).

And now...ready for the show! Put the SD card back in the ODROID device and boot your device.

Step 2 - First boot operations

The first time you boot you should connect through SSH to your device, default users have the following usernames/passwords:

root / root
user / user

As first operation change those passwords, and possibly you might want to use usermod to rename 'user' to something else.

After that re-generate the SSH keys:

sudo rm /etc/ssh/*_key /etc/ssh/*.pub
sudo dpkg-reconfigure openssh-server

Modify /etc/rc.local by adding these lines before the last exit 0 line (reported for reference):

cpufreq-set -g ondemand -d 200Mhz
chown .video /dev/ump
chown .video /dev/mali
chmod 0660 /dev/ump
chmod 0660 /dev/mali


Install now cpufrequtils package if you are not going to do Step 3.

Also make sure that your user is in the following groups:
user adm cdrom sudo audio dip video plugdev lpadmin pulse

Step 3 - Trimming down the installation (optional)

In this optional step (that is also untested!) I explain how to remove a lot of packages that come by default installed with Linaro Ubuntu, you can skip it if you prefer to customize it by yourself.

Download odroid-u2-slim-package-selections.txt and then restore the selections by running:

sudo apt-get install dselect
sudo dpkg --clear-selections
sudo dpkg --set-selections < odroid-u2-slim-package-selections.txt
sudo apt-get -y update
sudo apt-get dselect-upgrade

A lot of packages will be removed and you should get XFCE installed in place of Unity (although I advise using LXDE).

When you have finished, please run:

sudo dpkg-reconfigure -a

To go through all necessary configuration steps.

Please note that the display manager will also not work! So don't expect any output on HDMI yet. Real men/women use terminal ;)

Step 4 - Getting the bare metal hardware (acceleration)!

It is necessary to update the kernel to use proper Mali400 hardware-accelerated GPU drivers.

We will use the 13th February release:

wget http://dn.odroid.com/Ubuntu_U2/20130213/linux-3.0.63-odroidu2_20130213.tar.gz
tar xvfz linux-3.0.63-odroidu2_20130213.tar.gz
cd linux-3.0.63-odroidu2_20130213
rm fstab
sudo ./install.sh


At this point a reboot is necessary to make the new kernel effective, I will ask you for such reboot at a later step.

Now we will install the vendor-provided mali400 drivers:

wget http://dn.odroid.com/MALI400_R3P2/20130222/mali_packages.tar.gz
tar xvfz mali_packages.tar.gz
cd mali_packages
sudo dpkg -i mali400_2.1-13_armhf.deb mali400-dev_2.1-13_armhf.deb xf86-video-mali_1.0.1-7_armhf.deb
sudo rm -rf /usr/lib/arm-linux-gnueabihf/mesa-egl /usr/share/X11/xorg.conf.d/99-hkl_mali.conf


Please note that we are removing 2 objects here:
  • mesa-egl, because would prevent you from getting the Mali EGL acceleration
  • 99-hkl_mali.conf, that is the default Mali configuration and consitutes just a source of confusion (it always overrides your xorg.conf)

Step 5 - Build your own xf86-video-mali (optional)

This step is optional e.g. you don't need it, I am keeping it here for reference.
Install xorg-dev, xutils-dev, automake, autoconf and libtool, then download the sources from ARM website (I've used release of 11 March 2013 called Linux EXA/DRI2 and X11 Display Drivers r3p2-01rel1), then enter the proper directory and run the following script build.sh:

#!/bin/bash
set -e
ODFLAGS="-DUMP_LOCK_ENABLED=1 -mfpu=neon -mfloat-abi=hard"

autoreconf -rfi
CFLAGS="$ODFLAGS" ./configure --prefix=/usr
CFLAGS="$ODFLAGS" ASFLAGS="-mfpu=neon -mfloat-abi=hard" make -j5

This will quickly deliver an usable xf86-video-mali that you can use in conjunction with the mali400 driver package from step 4.

NOTE: on some older versions of autoconf you can only do autoconf -fi

Step 6 - Starting XFCE4

If you have not before, reconfigure X11 to allow any user:

sudo dpkg reconfigure x11-common

Make sure that "Anybody" is selected and save.

Now let's setup /etc/X11/xorg.conf:

Section "Device"
        Identifier "Mali-Fbdev"
        Driver  "mali"
        Option  "fbdev"           "/dev/fb6"
        Option  "DRI2"            "true"

        Option  "DRI2_PAGE_FLIP"  "false"
        Option  "DRI2_WAIT_VSYNC" "false"

        Option  "UMP_CACHED"      "true"
        Option  "UMP_LOCK"        "false"
EndSection

Section "Screen"
        Identifier   "Mali-Screen"
        Device       "Mali-Fbdev"

EndSection

Section "DRI"
        Mode 0666
EndSection


Please note the DRI2_PAGE_FLIP setting above, set to disabled. If you enable it your applications performance will start to thrash after a couple of minutes. For example RetroArch had a constantly falling down FPS because of this. I have also experienced instant crashes (SEGFAULT) with fullscreen applications using it.
Update 13 July 2013: The segfault was due to using the setting "DefaultDepth 16", and DRI2_PAGE_FLIP does no more show a negative behaviour, actually a positive one - so feel free to enable it. VSYNC can be enabled but it's not effective, see also this post

Update 05 May 2013: I have provided with a more recent version of xorg.conf here in this post, that adds only turning off DPMS

Now we're ready again. Reboot the system (and check that you are running kernel 3.0.63 through uname -a), then run:

startxfce4

XFCE4 will display in all its glory. Your Xorg.0.log will contain:

(EE) AIGLX error: dlopen of /usr/lib/arm-linux-gnueabihf/dri/Mali DRI2_dri.so failed (/usr/lib/arm-linux-gnueabihf/dri/Mali DRI2_dri.so: cannot open shared object file: No such file or directory)
(EE) AIGLX: reverting to software rendering
(II) AIGLX: Screen 0 is not DRI capable
(II) AIGLX: Loaded and initialized swrast
(II) GLX: Initialized DRISWRAST GL provider for screen 0

You can completely disregard the above as hardware acceleration will instead work, and we are now going to verify it.

Bit depth

By specifying a DefaultDepth of 24 you will get a segfault right after the GET_UMP_SECURE_ID_BUF1 line in the log.

Update 18 April 2013: libv has personally sent a patch to mdrjr so that HDMI output up to 32bit will be supported, stay tuned! :)
Update 21 April 2013: by recompiling the 3.0 kernel (provided by Hardkernel) with CONFIG_VIDEO_EXYNOS_24_FORCE=y you can use HDMI in 24 bit mode, many thanks to libv for the patch

Step 7 - Rotating horses and crates!

Now it's time to see hardware acceleration in action.

You can use 3 programs to check the status of hadware acceleration on your ODROID:
  • glxgears, a classic tool to test GLX
  • es2gears, for ES2 testing
  • glmark2-es2, that is actually a benchmark and you will score 92 if everything went right
If your hardware acceleration is enabled you will see FPS above 100 in all of them (although not in all glmark2-es2 tests).

If you verify hardware acceleration to be working, feel free to continue to step 7.

Step 8 - Time for RetroArch

Unfortunately I have not been able to use KMS with Mali 400, I think it's not supported, but I managed to use RetroArch in accelerated X11.

Let's download and compile RetroArch:

git clone https://github.com/Themaister/RetroArch.git
mv RetroArch retroarch 
cd retroarch
CFLAGS="-mfpu=neon -mfloat-abi=hard" ./configure --enable-x11 --enable-gles --enable-alsa --disable-oss --disable-jack --disable-pulse --disable-kms --disable-vg
ASFLAGS="-mfpu=neon -mfloat-abi=hard" make -j5


If you get gcc errors about virtual memory exhausted or other weird corruptions, try to set the governor to userspace for the length of compilation operations.

At this point you should have a compiled retroarch binary, we are ready for Step 8.

NOTE: I have only a small patch, you might want to use it in you have an error there (compiling with VG support):
diff --git a/gfx/vg.c b/gfx/vg.c
index c5b92e0..bbfc3a8 100644
--- a/gfx/vg.c
+++ b/gfx/vg.c
@@ -99,7 +99,7 @@ static void *vg_init(const video_info_t *video, const input_driver_t **input, vo
    RARCH_LOG("Detecting screen resolution %ux%u.\n", vg->mScreenWidth, vg->mScreenHeight);

    vg->driver->swap_interval(video->vsync ? 1 : 0);
-   vg->driver->update_window_title(true);
+   vg->driver->update_window_title();

    vg->mTexType = video->rgb32 ? VG_sXRGB_8888 : VG_sRGB_565;
    vg->mKeepAspect = video->force_aspect;
@@ -387,7 +387,7 @@ static bool vg_frame(void *data, const void *frame, unsigned width, unsigned hei
    if (msg && vg->mFontsOn)
       vg_draw_message(vg, msg);

-   vg->driver->update_window_title(false);
+   vg->driver->update_window_title();

    RARCH_PERFORMANCE_STOP(vg_fr);
    vg->driver->swap_buffers();


Step 9 - We need a core


RetroArch cannot do anything if you have no cores. Let's build snes9x-next.

git clone https://github.com/libretro/snes9x-next.git
cd snes9x-next
mv snes9x-next libretro-snes9x-next
make -j5 -f Makefile.libretro


Now you will have snes9x_next_libretro.so, take note of the path to this file by copying the output of:

ls $PWD/snes9x_next_libretro.so

Now let's go back into retroarch's working directory and run RetroArch:

DISPLAY=:0 ./retroarch -L /your/complete/path/snes9x_next_libretro.so SNES9X\ Demo\ V1.16\ \(PD\).smc

If you are typing this into an XFCE terminal, then you can omit the DISPLAY=:0 part.

Now you should see the ROM being emulated with FPS count on the window title bar.
You can install the other cores manually (one by one) or by using the libretro-super scripts.

Step 10 - Packing up together


It is advised to use different CPU settings when running retroarch; for this reason I use a script similar to this snes9x.sh:

#!/bin/bash
sudo cpufreq-set -g ondemand --min 1.6Ghz
DISPLAY=:0 ./retroarch -L /your/complete/path/snes9x_next_libretro.so $@
sudo cpufreq-set -g ondemand --min 200Mhz

This script will effectively change the minimum frequency when you are using RetroArch, and then restore it back when you exit (unless you use Ctrl+C, so don't!).

You can even use a higher minimum frequency if you experience slowdowns, however please pay attention that a fan might be needed when overclocking! Please refer to official ODROID information regarding this.

Step 11

SNES9X Demo ROM (Public Domain)

Enjoy it! :)

Conclusions


I think that ODROID-U2 has a lot of potential, I plan to do other interesting things in future with this development board.

Please let me know your feedback if there are errors or possibility of improvements by using the official ODROID forums discussion thread.

2013-03-29

Monodevelop rules!

I recently gave another look at Monodevelop. Wow. Just wow. A lot of progress has been done since last time I tried it.

Look at it, in all its XFCE glory:
Elegant and well-designed


And there is even NuGet support:
 
Look ma! Without hands!

I like the auto-completion even better than Visual Studio. It's a pity the IDE detects LINQ syntax and 'var' as errors, but still I can live with that.

A small edit

A change which I did was to modify /usr/share/liteide/litebuild/gosrc.xml regarding the build working directory, see highlighted part:


Conclusion

I usually don't have these nice words for most of the UIs I use on Linux, so compliments to all contributors and Xamarin for this quality open source product!

2013-02-10

Go-SDL with callback support: done!

It is always fashioning to discover the type of big challenges that can arise from an apparently trivial task, like porting an ncurses game to Go! language. It's like watching the unexpected chessboard developments that can happen between two beginners.

This time I wanted to add support for sound through SDL_Audio, so I came up with a decent square-wave generator and started using this Go-SDL fork for audio output.
Problem: SDL audio works with samples or callbacks, and my samples are generated on the fly, being simple PC-buzzer-like sounds.

Strangely enough, that Go-SDL package I found uses a very complex architecture of mutexes and hard-coded hacks to simulate possibility of sending audio synchronously from Go, and only continuous streaming is supported, no custom samples playing, although the API fingerprint seems like it could support it.

Without continuous playback, my game was condemned to display
ALSA lib pcm.c:7339:(snd_pcm_recover) underrun occurred
 from time to time during gameplay. And that sucks.

The cage of Love where Go
is currently held prisoner without
proper support of C integration
I came in contact with author, and the end of a short discussion I wanted to roll my own version using CGO callbacks, easy done, but then I met this guy:
runtime: cgo callback on thread not created by Go.
runtime: signal received on thread not created by Go.
I digged a bit and found out the reason behind it, basically Go language is not (yet) that well-integrated with C language.
However, thanks to Roger Peppe's callback package it is possible to use C callbacks in Go, like Gordon K. did for PortAudio. It is a hack, but a nice one.
At this point I was going to use PortAudio because it already uses that callback package, but PortAudio has an extra "feature": incredible garbage in the console terminal, and that was not going to be bearable for my little ncurses game.

So I armed my fingers and started coding a fix, here's the result:
https://github.com/neagix/Go-SDL
I removed most mutexes and synchronization black magic and I am now using a single synchronous channel for samples mixing, and it has also support of custom sound-generation callbacks. The cherry on top is that it comes with a nice PC-speaker buzz sound simulator, for all you nostalgic BEEP guys :)

Talk about how much you can learn with a such a simple game :)

At the end of this coding adventure I have to agree with Otstol that it is a huge limitation (to usage&adoption) that Go! language does not sport better callbacks support. I am quite sure all these fireworks will soon be obsolete because the Go Authors will fix this ;)

* = the game in question is Langwar, my battering ram used to discover the Go! language and also bring back what I recognize with some nostalgia as a classic game useful for learning programming

Update 16 June 2013: thanks to G. Klaus for letting me know about Go having fixed the issue, I have now updated my fork of Go-SDL

2013-02-03

The sorry status of Go! IDEs

It is indeed the IDE which makes a developer feel powerful or powerless in front of common modern development challenges; I have used the most common IDEs, amongst the best I recall Visual Studio 6, Borland Delphi and NetBeans, that I still use nowadays.

In my recent adventure at using Go! language to port a simple game, I've found that Go! does not (yet) have an IDE made with love and care for the language.

I've tried Go-IDE (horrible MDI, will reopen the same file and cause crosswrites), NetBeans with the (in)famous plugin (IDE will not search into .go extension files, no Ctrl+click support, no nothing, just syntax highlighting) and then reverted back to my good old Geany.

 
Actually I've found that with the changes explained here:

http://go-lang.cat-v.org/text-editors/geany/

It becomes a really good deal. Now back to coding ;)

Update 29 March: I found what I was looking for, golangide, awesome! :)

2013-01-27

The state of SNES emulation on Raspberry Pi

Some weeks ago I started tweaking basically all Snes9x forks around, questioning the possibility to run decent SNES emulation on Raspberry PI.

First, I went for the pure approach, porting the current Snes9x git master (1.53) to Raspberry Pi, that was however barely usable. byuu's new sound core is very precise but makes it slow (this has become riddle for me, right now).
As second attempt I merged the spc700 sound core from a snes9x-0.40 version (by notaz, ported to Symbian); this was effectively the pre-byuu sound core, and the backport was bloody. As a result, it didn't work: a few samples were being produced resulting in no sound at all.

On my third attempt I looked at the current Pandora port, snes9x-1.39ff, and that worked better; after some hard work it could successfully run. I added native OpenGL ES display support (already added to previous attempt) and then started tinkering with the input code. I stopped after finding a weird bug with the new keyboard input (game input freeze, possibly unrelated to my additions). Ideally I would have added native keyboard and joystick support.

Nowadays there's to say that I've lost most interest on working on this project, thus I've released my patched work as-is, and going on to my next challenge. :)

With this project I was slowly restarting with C/C++ and hacking around; this work, although not completely successful, has taken quite some effort! In the end I will listen to the advice of Toad King, that basically we don't have the numbers to make this work.

I don't want to set a trend of many interrupted projects, but eventually I will sit on something that I like :P

2013-01-20

My first RaspberryPi release

I have been tinkering a lot with Snes9x codebase and I was able to successfully use the hardware-accelerated display. Cool :)

In this process I've read many OpenGL ES tutorials and also seen some 2D examples about how to render on Raspberry PI, thus I wanted to properly format my achievements into a static library for multiple reasons: to help other newbies, to have it in good shape for my next Raspberry Pi 2D projects, and to sharpen my long-forgotten C++ skills :)

The library is C++ (with some C), not really packaged for portability but you should be able to use it with little efforts. There are some nice&interesting features, like:
  • support for hardware-provided scaling
  • tileset loading from PNG and index-based tile selection for drawing
  • render-to-texture (this is what you will use to port other software to Raspberry PI)
I am also using render-to-texture on the snes9x-rpi port (not yet released), thus I will mantain this library at least for some time.


Any feedback welcome! Enjoy

2013-01-05

RaspberryPi ideas

I have been playing/tweaking/hacking with my RaspberryPi for some months now. The device has indeed some use; its limited power is a good constraint to keep focused on good programming practices and embedded systems development, that is one area of expertize that I loved in the past and still fosters my curiosity.


Some projects that I would like to complete as a hobby are:

I will document the progress and of course properly publish the projects in a genuine open-source way.