Kodi and Advanced Mame on ODROID-XU4 - Part 2

This is a continuation of a guide for setting up Kodi with Mame, which details how to install the joystick. Ideally, playing with MAME requires a nice joystick. Here are two examples of joystick I've built myself. It's a good exercise of woodwork, painting, designing and electronics and a fun game for the family. I've made them with planks I collected from a construction site nearby. Good for the environment to recycle things too.

Figure 1 - Custom made Joystick for Kodi with Mame
Figure 1 - Custom made Joystick for Kodi with Mame

Figure 2 - Custom made Joystick for Kodi with Mame
Figure 2 - Custom made Joystick for Kodi with Mame

1. Install the software to support and calibrate the joystick. Arcade joysticks are easy to build or can be bought on Internet. They work very well and ideal for playing with MAME's arcade games.

$ sudo apt install joystick jstest-gtk

Calibrate the joystick

Since most Mame games will require a simple joystick with buttons, calibration will be very simple. You can use jstest-gtk, but because we already installed Kodi, we will do the calibration from the command line only.

With a click joystick, the only calibration is to associate buttons (inside the joystick for the directions and fire/select buttons), with their respective direction or function. The calibration will be available system-wide and therefore will be used by mame.

If you can plug your joystick into your Linux machine, I recommend to use a small program called jstest-gtk. It's a simple GUI, and you can check the proper direction of your joystick. In my case, I use a DragonRise compatible joystick (the one on the picture), with 4 connectors for up, down, left and right. But there are a few problems which we will fix with the calibration. First of all, the left-right and up-down are inversed and then the up-down axis is upside down. So to make it short: up is right, down is left, right is down and left is up!!! I can see that on the jstest-gtk interface.

Another option (since Kodi 17) is to setup your joystick directly from Kodi. A tutorial is available at https://kodi.wiki/view/HOW-TO:Configure_controllers. As there are many models of joystick, I won't cover all the possible configurations, but please contribute and I'll add your solution to this guide.

If you want to play with the joystick configuration and assign various command to each button or change the directions, you need to provide a configuration file. Let's call it myjoyremap.cfg. In my case, I use the following file, but yours might differ a lot depending on what you want to achieve and your joystick's model:

< ?xml version="1.0"? >
< mameconfig version="10" >
< system name="default" >
< input >
< port type="P1_JOYSTICK_UP" > < newseq type="standard" > JOYCODE_1_XAXIS_RIGHT_SWITCH < /newseq > < /port >
< port type="P1_JOYSTICK_DOWN" > < newseq type="standard" > JOYCODE_1_XAXIS_LEFT_SWITCH < /newseq > < /port >
< port type="P1_JOYSTICK_LEFT" > < newseq type="standard" > JOYCODE_1_YAXIS_UP_SWITCH < /newseq > < /port >
< port type="P1_JOYSTICK_RIGHT" > < newseq type="standard" > JOYCODE_1_YAXIS_DOWN_SWITCH < /newseq > < /port >

< port type="P1_BUTTON1" > < newseq type="standard" > JOYCODE_1_BUTTON1 < /newseq > < /port >
< port type="P1_BUTTON2" > < newseq type="standard" > JOYCODE_1_BUTTON3 < /newseq > < /port >
< port type="P1_BUTTON3" > < newseq type="standard" > JOYCODE_1_BUTTON5 < /newseq > < /port >
< port type="P1_BUTTON4" > < newseq type="standard" > JOYCODE_1_BUTTON7 < /newseq > < /port >

< port type="P1_BUTTON5" > < newseq type="standard" > JOYCODE_1_BUTTON2 < /newseq > < /port >
< port type="P1_BUTTON6" > < newseq type="standard" > JOYCODE_1_BUTTON4 < /newseq > < /port >
< port type="P1_BUTTON7" > < newseq type="standard" > JOYCODE_1_BUTTON6 < /newseq > < /port >

< port type="P1_BUTTON8" > < newseq type="standard" > NONE < /newseq > < /port >
< port type="P1_BUTTON9" > < newseq type="standard" > NONE < /newseq > < /port >
< port type="P1_BUTTON10" > < newseq type="standard" > NONE < /newseq > < /port >
< port type="P1_BUTTON11" > < newseq type="standard" > NONE < /newseq > < /port >
< port type="P1_BUTTON12" > < newseq type="standard" > NONE < /newseq > < /port >

< port type="P1_START" > < newseq type="standard" > JOYCODE_1_BUTTON9 < /newseq > < /port >
< port type="P1_SELECT" > < newseq type="standard" > JOYCODE_1_BUTTON10 < /newseq > < /port >
< port type="COIN1" > < newseq type="standard" > JOYCODE_1_BUTTON8 < /newseq > < /port >
< port type="START1" > < newseq type="standard" > KEYCODE_1 OR JOYCODE_1_BUTTON9 < /newseq > < /port >

< port type="P1_PEDAL" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq >
< /port > < port type="P1_PEDAL2" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < /port >
< port type="P1_PEDAL3" > < newseq type="increment" > NONE < /newseq > < /port >
< port type="P1_PADDLE" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P1_PADDLE_V" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P1_POSITIONAL" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P1_POSITIONAL_V" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P1_DIAL" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P1_DIAL_V" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P1_TRACKBALL_X" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P1_TRACKBALL_Y" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P1_AD_STICK_X" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P1_AD_STICK_Y" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P1_AD_STICK_Z" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P1_LIGHTGUN_X" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P1_LIGHTGUN_Y" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >

< port type="P2_JOYSTICK_UP" > < newseq type="standard" > JOYCODE_2_XAXIS_RIGHT_SWITCH < /newseq > < /port >
< port type="P2_JOYSTICK_DOWN" > < newseq type="standard" > JOYCODE_2_XAXIS_LEFT_SWITCH < /newseq > < /port >
< port type="P2_JOYSTICK_LEFT" > < newseq type="standard" > JOYCODE_2_YAXIS_UP_SWITCH < /newseq > < /port >
< port type="P2_JOYSTICK_RIGHT" > < newseq type="standard" > JOYCODE_2_YAXIS_DOWN_SWITCH < /newseq > < /port >

< port type="P2_BUTTON1" > < newseq type="standard" > JOYCODE_2_BUTTON1 < /newseq > < /port >
< port type="P2_BUTTON2" > < newseq type="standard" > JOYCODE_2_BUTTON3 < /newseq > < /port >
< port type="P2_BUTTON3" > < newseq type="standard" > JOYCODE_2_BUTTON5 < /newseq > < /port >
< port type="P2_BUTTON4" > < newseq type="standard" > JOYCODE_2_BUTTON7 < /newseq > < /port >

< port type="P2_BUTTON5" > < newseq type="standard" > JOYCODE_2_BUTTON2 < /newseq > < /port >
< port type="P2_BUTTON6" > < newseq type="standard" > JOYCODE_2_BUTTON4 < /newseq > < /port >
< port type="P2_BUTTON7" > < newseq type="standard" > JOYCODE_2_BUTTON6 < /newseq > < /port >

< port type="P2_BUTTON8" > < newseq type="standard" > NONE < /newseq > < /port >
< port type="P2_BUTTON9" > < newseq type="standard" > NONE < /newseq > < /port >
< port type="P2_BUTTON10" > < newseq type="standard" > NONE < /newseq > < /port >
< port type="P2_BUTTON11" > < newseq type="standard" > NONE < /newseq > < /port >
< port type="P2_BUTTON12" > < newseq type="standard" > NONE < /newseq > < /port >

< port type="P2_START" > < newseq type="standard" > JOYCODE_2_BUTTON9 < /newseq > < /port >
< port type="P2_SELECT" > < newseq type="standard" > JOYCODE_2_BUTTON10 < /newseq > < /port >
< port type="COIN2" > < newseq type="standard" > JOYCODE_2_BUTTON8 < /newseq > < /port >
< port type="START2" > < newseq type="standard" > KEYCODE_2 OR JOYCODE_2_BUTTON9 < /newseq > < /port >

< port type="P2_PEDAL" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq >
< /port > < port type="P2_PEDAL2" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < /port >
< port type="P2_PEDAL3" > < newseq type="increment" > NONE < /newseq > < /port >
< port type="P2_PADDLE" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P2_PADDLE_V" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P2_POSITIONAL" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P2_POSITIONAL_V" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P2_DIAL" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P2_DIAL_V" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P2_TRACKBALL_X" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P2_TRACKBALL_Y" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P2_AD_STICK_X" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P2_AD_STICK_Y" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P2_AD_STICK_Z" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P2_LIGHTGUN_X" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >
< port type="P2_LIGHTGUN_Y" > < newseq type="standard" > NONE < /newseq > < newseq type="increment" > NONE < /newseq > < newseq type="decrement" > NONE < /newseq > < /port >

< /input >
< /system >
< /mameconfig >
After saving the file, copy it to /media/usb/AML-assets/ctrlr/. Then, you can edit this file to adjust it to your own joystick. My joystick (which I built myself, hence the problem mentioned above) has a 90 degrees misconfiguration. In the XML file, you have two parts: one for the Player 1 joystick and another part for the Player 2 joystick. Each line with type="P1_JOYSTICK_UP" is the direction as understood by Mame. Then, the real configuration comes after as JOYCODE_1_XAXIS_RIGHT_SWITCH. Therefore, this line means that when my joystick sends a code for RIGHT, mame will interpret it as UP. Below this, I configured the buttons 1 to 8 and the START and SELECT buttons. Then I do the same for the Player's 2 joystick.

Finally, you can add it to the mame.ini configuration file by using the following command:

$ echo "ctrlr myjoyremap" | sudo tee -a /etc/mame/mame.ini

Remove unused software

This section is not mandatory, but you can find it useful to make your ODROID-XU4 lighter and more responsive. The XU4 has 2GB of memory, which is currently considered good for a Single Board Computer. Most of them have 0.5 to 1GB, but I see some 2 to 4 GB finally coming onto the market. So memory is a precious resource as well as CPU cycles. You don't want any slowdown of your machine while watching a movie or playing a game.

I selected a few services which I think are not necessary for a Kodi/Mame installation. Here is the way to stop and disable them. However, we will not uninstall the software, so that you can enable them again, should your needs change in the future.

1. CUPS is a print server, and since you don't really need to print from Kodi or Mame, it's safe to remove the print server (named CUPS):

$ sudo systemctl stop cups
$ sudo systemctl stop cups-browsed
$ sudo systemctl disable cups
$ sudo systemctl disable cups-browsed
To re-enable it:
$ sudo systemctl enable cups
$ sudo systemctl start cups
2. UPower controls the power source, and is useful with a smartphone, laptop or embedded system. However, in the case of a Kodi/Mame entertainment system in your living room, the only power source is the socket wall and your ODROID-XU4 is supposed to be connected all the time. So you can safely remove this one too:
$ sudo systemctl stop upower
$ sudo systemctl disable upower
3. Whoopsie is the error reporting daemon for Ubuntu, mainly used by desktop environment when something crashes. As we're only using Kodi, it's not necessary here:
$ sudo systemctl stop whoopsie
$ sudo systemctl disable whoopsie
4. ModemManager is a daemon which controls mobile broadband (2G/3G/4G) devices and connections. The ODROID-XU4 is connected to an ethernet (or a wifi if you have one) and does not need a _modem_ connection.
$ sudo systemctl stop ModemManager
$ sudo systemctl disable ModemManager
5. unattended-upgrades is a daemon to automatically update the system. I like when a computer works for me but in this specific case, we will avoid doing any automatic update. The reason is we want a stable entertainment system for all the family, which is available at any time. We don't want to have to do maintenance, just before launching the family movie, because an update didn't work:
$ sudo systemctl stop unattended-upgrades
$ sudo systemctl disable unattended-upgrades
If you want to upgrade your ODROID-XU4, you can still do it manually by running first an update of the packages' database:
$ sudo apt update
$ sudo apt upgrade
Personally, I'm a big fan of a software called Synaptic, which is a GUI for apt-based systems like Ubutun and Debian. I recommend it:
$ sudo apt install synaptic

Set the clock

You can synchronize the clock to a time server on the net and always have your ODROID set to the most accurate time. Moreover, you want to set the clock to your timezone.

First, we install a Network Time Protocol (NTP) client which will connect to time server to get an accurate time:

$ sudo apt install chrony
Then, we search for the time zone. It will be something like Europe/Zurich or Pacific/Auckland. To find yours, use the following command:
$ timedatectl list-timezones
Search and note your own time zone. Let's say you live near the North Pole in Longyearbyen, you will find the time zone in the list given above as Arctic/Longyearbyen. Then, tune your ODROID-XU4:
$ sudo timedatectl set-timezone Arctic/Longyearbyen
For comments, questions, and suggestions, please visit the original ODROID Forum thread at, https://forum.odroid.com/viewtopic.php?f=52&t=34760, or the GitHub repository at https://github.com/yimyom/odroid-xu4-setup.

Be the first to comment

Leave a Reply