Improve Powkiddy V90 with RetroArch and Quick Resume
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 their game backups 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 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 game backups up to around SNES/GBA. It runs Sega MegaDrive/Genesis backups perfectly, with a pixel-perfect resolution to match which is ideal for a Sonic the Hedgehog 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.
Portable but inconvenient
While there are a number of user experience issues with this device, the worst by far is the lack of proper standby and the need to go through a multi-stage power off process:
- Exit whatever application is open.
- Select "Power off" in the menu or hold a button combination.
- 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:
- Snes9X 2005 core isn't great.
- There is no FinalBurn Alpha/Neo core. MAME cores are too slow.
- No apps. Just emulation.
- Brightness must be adjusted using
main/.backlight.conf
(1 to 10). - Volume maximum must be adjusted using
main/.volume.conf
(0 to 9).- You can of course still use the volume dial to lower current volume.
There is no battery indicator.
Configuring RetroArch
RetroArch also has various features to improve the user experience. We can:
- Assign shortcuts to quit at any point.
SELECT
as a hotkey trigger andSTART
for quitting (either double press or hold) works well.
- Save state before quitting
- Auto loading the last state when continuing.
- Various UI features supported by RGUI. Some examples:
- Showing screenshots and cover art for each game. Great for slow readers!
- Themes and animations.
- Battery indicator.
- Configure each emulator core separately for optimised visuals.
There's a lot more you can configure and RetroArch's RGUI interface is so much more polished, consistent and pixel-perfect.
Implementing Quick Resume
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. This is often known as "Quick Resume".
I haven't properly looked into providing a way to sleep/suspend through Retroarch 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.
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.