the RG351MP
the software
I have no idea what the factory shipped, I was afraid of anbernic-poisoning so I immediately went to flash ArkOS … 3 times… unsuccessfully and then settled for 351elec @ https://351elec.de/.
elec was a new experience for me. Linux, yes, but everything runs as root, there are no users, no homes, not even a package manager. Getting dotnet and monogame up and running was quite the adventure.
Now, what can this thing do? Let’s look at the hardware so we can get a rough idea about its capabilities.
CPU: RK3326
The official Anbernic Store says its a 1.5ghz CPU, that however is a lie. It runs at 1.3ghz. I’ll be taking a look at overclocking later, maybe I can make it true.
- Quad-core ARM Cortex-A35 CPU
- ARM Neon Advanced SIMD
- ARMv8 Cryptography Extensions
- 256KB unified system L2 cache
- VFPv3 single and double-precision
Alright, so we’re dealing with an Ultra-Low-Power CPU from long-long-ago. The L2 cache is hilariously small, there’s no L3 cache at all. 1GB of DDR3L RAM is not fast either and the GPU will share it with the CPU, making it even slower. Small cache, slow RAM, I’m predicting a memory bandwidth bottleneck. At least it can do SIMD, so we can vectorize our code. Now let’s look at the GPU.
GPU: Mali G31 MP2
Further research shows it’s running at 650 MHz, has two cores and can push 1,3 GPix/s, 980 MT/s or 21.4 GFLOPs. Interestingly, ARM claims 4x MSAA has almost no performance overhead - we’ll see about that! Also surprisingly, it supports Vulkan!
APIs
- OpenGL ES 3.2
- Vulkan 1.1
- OpenCL 2.0
- h264,h265,VP9 - Decode & Encode
handheld xbox
So we’re basically working with an original xbox in terms of performance - with some extra CPU cores and newer feature-sets. Sweet.
Anbernic was smart enough to use a low resolution screen, namely a 3.5”, 640x480 @ 60hz IPS screen.
Most manufacturers would have slapped a 720p or 1080p screen on it just for marketing and cripple the rest of the hardware, but at 640x480, there aren’t many pixels to push.
I want to add that the screen is super crisp. The resolution is more than enough for the size.
getting distracted
Suikoden, Pokemon, Earthbound, Batsugun, Alien Soldier, Advance Wars 2, Tekken 3…. I’ve already wasted a couple of hours writing this post, even at this moment, it’s next to me playing some demo videos of random games as screensaver (which you can jump into by pressing start, launching the game that’s currently playing, super cool!) begging me to pick it up or at least look at it.
Can’t wait to play some more Destruction Derby later, but the dog will want out before I’m done writing. Ugh.
game development
The primary reason for me to even buy this device has been to give me some additional motivation for creating games. I want to target the RG351 directly and make it my primary platform. I figured becoming a console game developer would be cool as it would impose a lot of hard limitations on me - not only in terms of performance, but also input methods and screen size.
elec is a readonly OS. Every reboot - it resets. Persistent storage is only possible in /storage
. Which is the 2nd uSD card in the RG351MP. That’s fine by me.
Since elec has no real shell, ships almost no libraries and has no terminal, we need to setup a couple of things like a script to launch our game and find/ship all the files required for the game to function. On MonoGame you need to ship libGL.so.1
and libEGL.so.1
.
351elec is a 64bit OS and the RK3326 is an ARM CPU, that makes our dotnet command
dotnet publish -c release -r linux-arm64
but first we have to enable single file output.
csproj
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6</TargetFramework>
<MonoGamePlatform>DesktopGL</MonoGamePlatform>
<TieredCompilation>false</TieredCompilation>
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>true</SelfContained>
</PropertyGroup>
now we scp the contents of the publish folder and create our little launcher script
#!/bin/bash
gamedir="/storage/roms/ports/test/"
if [ -d "/opt/system/Tools/PortMaster/" ]; then
controlfolder="/opt/system/Tools/PortMaster"
elif [ -d "/opt/tools/PortMaster/" ]; then
controlfolder="/opt/tools/PortMaster"
elif [ -d "/roms/ports" ]; then
controlfolder="/roms/ports/PortMaster"
elif [ -d "/roms2/ports" ]; then
controlfolder="/roms2/ports/PortMaster"
else
controlfolder="/storage/roms/ports/PortMaster"
fi
echo "Starting Pixel Engine (.net6, C#10, ECS) by https://her.st/" > /dev/tty0
source $controlfolder/control.txt
source $controlfolder/tasksetter.sh
export LIBGL_ES=31
export LIBGL_FB=4
export SDL_VIDEO_GL_DRIVER="$gamedir/libs/libGL.so.1"
cd $gamedir
$GPTOKEYB "Pixel" -c "./test.gptk" &
$TASKSET ./Pixel > /dev/tty0
kill -9 $(pidof gptokeyb)
printf "\033c" >> /dev/tty0
map.gptk:
back = esc
start = enter
a = enter
b = up
x = \"
y = \"
l1 = mouse_right
l2 = mouse_right
r1 = mouse_left
r2 = mouse_left
up = w
down = s
left = a
right = d
left_analog_up = up
left_analog_down = down
left_analog_left = left
left_analog_right = right
right_analog_up = mouse_movement_up
right_analog_down = mouse_movement_down
right_analog_left = mouse_movement_left
right_analog_right = mouse_movement_right
deadzone_triggers = 3000
mouse_scale = 8192
mouse_delay = 16
The “game” will now show up in 351elec and you’ll be able to launch it.
That’s as far as I got in a day. Documentation didn’t exist so I had to reverse engineer other ports to figure out how to port >.> I got my PixelGlue engine running, tomorrow I’ll get inputs working properly…
conclusion
For game development on the RG351MP, the architectural choice seems obvious -> ECS
We need to hit the cache or we cripple the GPU with increased memory bandwidth requirements from the CPU side. It will be essential to use all four cores as they’re rather weak.
Vulkan goes without saying, however that’s out of reach for me at this point. I lack the required skills.
- It’s smaller yet heavier than expected (i didn’t check the measurements)
- The D-PAD lacks a center pin, it can press all directions at once - and often does so
- The screen isn’t very vibrant and quite dim - no usage outdoors if sun
- The sound is meh. NO bass, muddy mids, exaggerated highs.
- The battery life seems to be 5 hours, not 8
- You can’t really use both analog sticks at once due to ergonomics
- Too slow for N64, Dreamcast, PSP.