Tuesday, 13 September 2011

Installing mupen64plus on Pandaboard ( OMAP4 )

Well, here is my first more or less tutorial.

To install and configure mupen64plus and gles2n64 plug-in  on Pandaboard.

- You are running Linux on Pandaboard ( or perhaps any other OMAP4 board )
- You have a working Internet connection
- You have installed all GPU drivers ( GLES1, GLES2, EGL, OpenVG, DRI etc ) and they are working
- You are running everything in GUI
- You have a working native toolchain ( GCC, G++, Make, etc )

OS: Ubuntu Linux ( Maverick - 10.10 )
Kernel: 2.6.35-980-omap4
All OMAP add-ons ( which contain GPU drivers ) have been installed using apt-get from TI OMAP trunk PPA
HDMI Ready TV is used as video output
Video input: 1080p
Video output: 1080i

( This is not the only method of course, but it does work, at least for me. )

1) Install mupen64plus from your repo. On Ubuntu it would be:
sudo apt-get install mupen64plus

( This is the best way to make sure that you will be able to use your ARM+GLES2 optimised mupen64plus when you have installed and configured it. )

2) Run it and choose some ROM to test:
cd /usr/games && ./mupen64plus
cd /usr/local/bin && ./mupen64plus
( This is needed to see if your ROMs actually work with a standard build of mupen64plus. Because if they don't, there is no point trying to get them to work with an ARM optimized version of an emulator.  )

3) Now lets get our hands on a working binary of mupen64plus with an ARM Dynamic Recompiler. The easiest way to get one is by downloading a PND made for Pandora console. ( A lot of thanks to OpenPandora team and all developers ! )
( Thanks to sebt3 for providing the pnd. )
 wget http://sebt3.openpandora.org/pnd/mupen.pnd

4) To extract the pnd we will need to use the "unsquashfs" program.
Download, extract and make it executable by running:
wget http://zx81.zx81.free.fr/public/pandora/hack/unsquashfs.gz && gzip -d unsquashfs.gz && chmod +x unsquashfs
Run this to extract the contents of the pnd:
 ./unsquashfs mupen.pnd
NOTE: The result will be a folder named "squashfs-root" in the current directory.
NOTE2: If you want to use pnds in the future, it would be smart to install the unsquashfs binary. Run:
sudo cp unsquashfs /usr/bin
su &&  cp unsquashfs /usr/bin
Now you can just use "unsquashfs (pnd name)" to extract a pnd.

5) Install the binary of this mupen64plus. On Ubuntu you would copy it to /usr/games, so that you will be able to run it from a menu.
sudo cp -f squashfs-root/mupen64plus /usr/games
Lets also install all of the plugins, some of which may be handy. ( Like a built gles2n64 driver. ) Run:
 sudo cp -f -r squashfs-root/plugins /usr/share/mupen64plus

6) Now, lets build the gles2n64 driver from source. Download it: ( You will need the subversion client for this. )
 svn checkout http://gles2n64.googlecode.com/svn/trunk/ gles2n64-read-only
 The default Makefile is not going to work for anyone, except the author :D ( All directories listed in the makefile are for Windows and specifically  for his Windows box.  ) So, you will need to edit it. Firstly, modify this part:

CXX = $(COMPILER_DIR)/bin/arm-none-linux-gnueabi-g++
LD = $(COMPILER_DIR)/bin/arm-none-linux-gnueabi-g++
INCLUDE = C:/Users/jim/Desktop/Lachlan/Pandora/include
CFLAGS += -I$(INCLUDE)/libpng12
CFLAGS += -I$(COMPILER_DIR)/arm-none-linux-gnueabi/libc/lib
CFLAGS  += -march=armv7-a -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp -ffast-math \
    -fsingle-precision-constant  -ftree-vectorize -fexpensive-optimizations -fomit-frame-pointer
 so that it looks like this:

CXX = $(COMPILER_DIR)/bin/g++
LD = $(COMPILER_DIR)/bin/g++
INCLUDE = /usr/include
CFLAGS += -I$(INCLUDE)/libpng12
CFLAGS += -I$(COMPILER_DIR)/arm-none-linux-gnueabi/libc/lib
CFLAGS += -march=armv7-a -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp -ffast-math -fsingle-precision-constant -ftree-vectorize -fexpensive-optimizations -fomit-frame-pointer
Next, edit this part:
ifeq ($(OS), LINUX)
CFLAGS += -Wall -D__LINUX__ -fPIC
LDFLAGS += -LC:/Users/jim/Desktop/Lachlan/Pandora/OS/20101302-pandora-xfce/usr/lib
LDFLAGS += -lEGL -lGLESv2 -lsrv_um -lSDL-1.2 -lpng12 -lz -lIMGegl
LDFLAGS += -lX11 -lts-1.0 -lXau -lXdmcp -shared
CFLAGS += -Wall
LDFLAGS +=  -LC:/MinGW/lib/PVR -lSDLmain -lSDL -lpng -lGLESv2
to this:
ifeq ($(OS), LINUX)
CFLAGS += -Wall -D__LINUX__ -fPIC
LDFLAGS += -LC:/usr/lib
LDFLAGS += -lEGL -lGLESv2 -lsrv_um -lSDL -lpng12 -lz -lIMGegl
LDFLAGS += -lX11 -lXau -lXdmcp -shared
CFLAGS += -Wall
LDFLAGS += -lSDLmain -lSDL -lpng -lGLESv2
Now our Makefile is ready to work. Apart from directories I have also changed "-mtune=cortex-a8" to "-mtune=cortex-a9" to gain some optimizations for Cortex A9 CPU. Also, I have removed -lts-1.0 CFLAG, because ld failed to load a library that doesn't even exist. ( Why I didn't install it you want to ask ? Because I don't know what on earth is the name of this library. Google was so useless trying to find a library using three characters ... ). Finally I edited some CFLAGS and LDFLAGS.
Next we will modify two other files. Edit OpenGL.h. This is the part we need:
#ifndef OPENGL_H
#define OPENGL_H

#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES2/gl2extimg.h>
#include "winlnxdefs.h"
#include "SDL.h"
#include "gSP.h"
Remove or comment out ( add // at the start of the line ) "#include <GLES2/gl2extimg.h>". We don't have this header. ( At least in Maverick's PPA. )
Now modify the file OpenGL.cpp. Remove this part: ( shold be at line 490 )
                    printf("Incomplete Formats. \n"); break;
Ye, I know it is a dirty and unrecommended way of dealing with a problem related to source files. There must be a cleaner and smarter way. But it does work. ( With these two lines in place the compilation always failed. I am not a programmer, so I had to rely on logic alone.)

Before you can run make you will need to install SDL headers. On Ubuntu it would be:
 sudo apt-get install libsdl1.2-dev
cd gles2n64-read-only && make all && cd ..
You should end up with a "gles2n64.so" shared library. Copy it into your plugin directory:
 sudo cp -f gles2n64-read-only/gles2n64.so /usr/share/mupen64plus/plugins
Now you can use a newly created gles2n64 driver :D

7) Start your new mupen64plus:
cd /usr/games && ./mupen64plus
( No rom is needed. ) Go to your home directory, make hidden files visible and see if you have a folder named .mupen64plus. In that folder there should be a file named gles2n64.conf. Edit it:
"window enable x11" should be 1
"window centre" should be 1
"window fullscreen" should be 0
"framebuffer enable" must be 0 ( otherwise you will have no output )

"screen width" "screen height" "window width" "window height" control the dimensions of the gles2n64 output. If your Pandaboard outputs 1080p, I would recommend using about 1810 for width and 970 for height.
There also should be a file named mupen64plus.conf in the same directory. We will point mupen to required plugins. Modify:
Gfx Plugin = gles2n64.so ( we will use this of course )
Audio Plugin = jttl_audio.so ( there is also plugin by Notaz, but it requires OSS I think )
Input Plugin = which one you prefer ( I use blight_input.so )
anything else you would want.

That's all. You would also probably need to configure your controller. ( I use SixAxis. ) Enjoy your games !

I made them quickly ...

Turok 2 Seeds of Evil

Star Fox 64

( All roms are PAL. Played all games nearly at 1080p. All plug-ins except gfx are standard. Mupen64plus uses one core. Frequency = 1GHz )

Turok 2 Seeds of Evil - works perfectly, certainly playable, some minor graphics glitches. FPS = 12 - 26

Turok Dinosaur Hunter - same as Turok 2

Star Fox 64 - excellent, very little graphics bugs. Sound playback is not that good, but ok. FPS = 12 - 30

Resident Evil 2 - doesn't work at all ( errors related to dynamic recompiler )

Quake 64 - not so fast as I would expect it to be, major graphics glitches, sound delays, not enjoyable to play. FPS = 11 -20