jahed.dev

Improving Powkiddy V90's Portable Experience with RetroArch

I've recently started following the retro handheld gaming scene. It's a seemingly growing market of people, usually nostalgia-driven enthusiasts, who want to play discontinued games on a portable device using emulation. There was a peak in interest recently after the release of the Analogue Pocket, a high-end offering in what is typically a low-end market.

Discovering this market was a coincidence. I researched into cheap handheld gaming devices for a children's gift and ended up down this rabbit hole thanks to YouTube. In the end, I went for a Powkiddy V90. It's a US$40 clamshell device able to run games up to around SNES/GBA. It runs Sega MegaDrive/Genesis games perfectly, with a pixel-perfect resolution to match which is ideal for a Sonic fan. It even has its own custom firmware, an active community, and official builds of RetroArch. The hardware experience is also spot on. The clamshell form factor makes it pocket-able and protects the screen. For its price, it's a beast.

Powkiddy V90 display showing RetroArch with Sonic Blast highlighted and screenshot thumbnails to the side.
Powkiddy V90 running RetroArch.

Of course, it has its problems. Its software experience isn't friendly; specially for children. The custom firmware improves some things, but it's still not great.

Portable but inconvenient

The worst part of using this device is the lack of proper standby and the need to go through a multi-stage power off process:

  1. Exit whatever application is open.
  2. Select "Power off" in the menu or hold a button combination.
  3. Switch off using the physical power switch.

Failure to follow these steps and skipping to the power switch will potentially cause the memory card to corrupt. If the memory card's fine, there's a long boot up process to ensure the filesystem hasn't corrupted.

Each application has its own button mappings and exit process. There's no universal standby mode, nor a way to quickly jump back into a game. There's even a really slow, green and loud "Powkiddy" boot up logo that can't be skipped.

Trying to explain all these limitations to a child is impossible, no matter how many times I have to re-flash their memory card. So what's the solution? Improve everything!

Before we start

To edit various files, we'll need to be able to mount the rootfs partition of your microSD card to whichever computer you're using. Linux-based operating systems will have no issues with this; it'll mount like any other partition. For other operating systems like Windows and macOS, I'll leave that for you to figure out.

To be extra careful, now is a good time to backup your microSD card. Most disk management software will let you create a disk image of your card which you can restore at any time.

Disable the boot logo

To speed up the boot process and make it less hideous, an easy first step is to disable the boot logo. Either delete the main/boot-logo file or disable the step entirely in the boot-up script under rootfs/etc/main.

# rootfs/etc/main
#if [ -e $BOOTLOGO ]
#then
#/mnt/boot-logo > /dev/null 2>&1
#fi

Disabling filesystem checks?

Within the same boot-up script is the filesystem check. Since I can't prevent unsafe shutdowns, what's the point of that check? If it's corrupt, it's corrupt... right?

# rootfs/etc/main
#Check if fat32 is flagged as "dirty", and if so unmount, repair, remount
if dmesg | grep "mmcblk0p4" > /dev/null;  then
  echo -e "\e[31mUnclean shutdown detected.\e[0m"
  echo -e "\e[32mChecking FAT32 partition...\e[0m"
  umount /dev/mmcblk0p4
  fsck.vfat -y /dev/mmcblk0p4 > /dev/null;
  mount /dev/mmcblk0p4 /mnt -t vfat -o rw,sync,utf8
  echo -e "\e[32mCheck complete.\e[0m"
fi
clear

Well, no. As I found out a few days later, the check also repairs issues. I mean, the comment right above it says so. Disabling it will increase the risk of corruption. The real solution is to make the shutdown process simpler and convenient. To do that we'll need to...

Boot into RetroArch

Miyoo Custom Firmware ships with a frontend called GMenu2X. It's an application launcher which lets you pick a file to launch with. As I mentioned, each application is its own thing, there's no universal shell. So GMenu2X's standby, poweroff and other features aren't available. In fact, it shuts itself down after launching an application. The only reason it comes back up is because of an infinite loop in the boot script.

# rootfs/etc/main
while [ 1 ]
do
  if test -f "$START"; then
    source $START
      else

          cd /mnt/gmenu2x;
          ./gmenu2x > /dev/null 2>&1;
  fi
        clear
done

I left the formatting as-is. It's not mine!

Without a universal shell, it's impossible to improve anything... universally.

Luckily, I noticed RetroArch released a new version recently, which got me wondering. Why don't I launch straight into RetroArch? It's kind of a universal shell. Being a popular solution for retro homebrew devices, it probably does everything I need. So we just need to replace the code above like so...?

# rootfs/etc/main
cd /mnt/emus/retroarch
./retroarch > /dev/null 2>&1
clear

Not quite. rootfs/etc/main is configured with respawn in rootfs/etc/inittab. So when RetroArch exits, the system hangs and then restarts after a few seconds. Shutting down during this cycle again causes corruption.

GMenu2X is doing something different. After some digging around its source code, I noticed its exit process has this line:

// src/gmenu2x.cpp
system("sync; poweroff");

So it's flushing and powering off by shelling out. Simple enough.

# rootfs/etc/main
cd /mnt/emus/retroarch
./retroarch > /dev/null 2>&1
clear
sync
poweroff

Done! Now when RetroArch exits, we instantly do a safe shutdown.

RetroArch limitations

It's worth mentioning that you'll lose a few things when moving to RetroArch. So you might want to keep a backdoor open for GMenu2X. These aren't major issues for me so I removed everything unrelated to RetroArch, including GMenu2X and all the various bundled applications and ports.

If the Miyoo/RetroArch community has the time, I'm sure these limitations can be improved upon. Here's a few things:

Configuring RetroArch

RetroArch also has various features to improve the user experience. We can:

There's a lot more you can configure and RetroArch's RGUI interface is so much more polished, consistent and pixel-perfect.

Pick up and play

So now, it's easy to power off safely. But being a handheld, it's more convenient to be able to stop whenever we want and start exactly where we left off quickly.

I haven't properly looked into wiring up sleep/suspend yet. GMenu2X's "suspend" feature seems to work by disabling the backlight and lowering CPU clocks, so I'm not sure if it's worth implementing. Instead, we can make use of RetroArch's auto save/load state and history features for a similar experience. RetroArch doesn't support this directly, but we can write a workaround.

# rootfs/etc/main
cd /mnt/emus/retroarch
if ! read -n 1 -t 1 -s; then
  local history_path='/mnt/.retroarch/content_history.lpl'
  if test -f "${history_path}"; then
    local rom_path="$(head -n20 "${history_path}" | grep -Eo -m1 '/mnt/roms/[^"]+')"
    local core_path="$(head -n20 "${history_path}" | grep -Eo -m1 '/mnt/.retroarch/cores/.+\.so')"
    if test -f "${core_path}" -a -f "${rom_path}"; then
      clear
      echo -e "\n\n\n\n\n\n\n\n\n\n\n\n\n\n              \e[1;33m[ LOADING ]\e[0m"
      ./retroarch --load-menu-on-error --libretro "${core_path}" "${rom_path}" > /dev/null 2>&1
      return
    fi
  fi
fi
./retroarch --menu > /dev/null 2>&1
clear
echo -e "\n\n\n\n\n\n\n\n\n\n\n\n\n\n               \e[1;33m[ SAVING ]\e[0m"
sync
poweroff

The echo lines are for presentation. Rather than a black screen, you'll see a coloured status centered on the screen while things are getting prepared.

It's ugly but it works! We essentially grab the most recent content in history and launch RetroArch straight to it. You can also hold SELECT down during boot up to skip this step and go into the usual start screen. It adds a 1 second wait, but that's not a big deal.

Booting straight into an automatic save state in RetroArch, along with a speedy safe shutdown. The video uses a 2 second wait, but 1 second works just as well.

Conclusion

After all of these changes, we now have a near perfect pick up and play experience. You can start a game, power-off, power-on and continue immediately where you left off. The manual power switch still kind of sucks, but that's tied to hardware.

Powkiddy V90, MiyooCFW, and RetroArch are an amazing combination. With their active communities, I'm sure they'll keep getting better.

It's been a few years since the V90 released and it's strange that no other, or at most very few, retro handhelds are using a compact clamshell design. I wonder if there'll ever be a V100?

You can find the final rootfs/etc/main script here.

Thanks for reading.