So I ended up picking up an RG280V last week and it arrived over the weekend. I'm very pleased that I decided to get it, and managed to work with it a fair amount over the weekend, including trying different retroarch emulators for it. I replaced the stock image with the Adam Image, which is designed for the RG350, but it runs the same chip as the RG280V. Retrogamecorps published a starter guide that got me off the ground without too much trouble.
The whole system is built on OpenDingux, and runs Retroarch targeting the framebuffer for emulation (no X or window management). The processor is a MIPS processor, so in theory I could take SDL 1.2/2.0 apps for Linux and recompile them and package as an opk
for the system. This requires cross-compilation, which I'm not very familiar with.
The particular app I want to bring over is ECWolf: an enhanced source port of Wolfenstein. I really want to play through the original again, and doing it on the RG280V is a perfect fit. ECWolf has some compilation guidelines on the wiki, but it doesn't cover this case. I tried the precompiled binary in one of the app repos on GitHub, but when I launch Wolfenstein (ECWolf), it just crashes.
The actual link to the patch utility on the page for x86_64 is broken because he changed from bz2
compression to xz
and forgot to update the links.
The internet thinks this is about my data files, but I patched my data files with the ECWolf utility for data file patching to bring them up to date, but still no joy. I also validated the checksums against the canonical checksums that each file should have over on the ecwolf wiki, which also did not help.
Anyway, the data files aren't the problem. I changed the RG280V to use a USB mode for linux that will mount it via cable as an ethernet device, which then allows me to SSH into it with username od
and password untoqebboqvboqudrn
. I'm putting that here for reference: it's documented on the Adam image page under "System Access". I'm using version 1.3.1 of the image, I believe, and this approach let's me scp
files to the system rather than pulling out the cards constantly.
So I get shell access, and learn there is no package manager. I also find the opk
files, and learn that I can run them with opkrun
. This reveals the true error: ecwolf.opk
was compiled with an optional dependency on libbz2 enabled, and the shared library can't be found on the Adam image. Since there's no package management, it's not easy to install, and I haven't been able to find a version online.
So my strategy is to set up cross compilation targeting the 1.0GHZ JZ4770 CPU in the unit. I found a guide that should get me started with this, but I will then need to apply that approach to the ecwolf source code and see if I can produce an opk
with minimal system dependencies. ecwolf uses CMake, which I'm not super familiar with outside of compiling OpenMW from time to time, so this will be a fun learning experience!
A day passes...
After about ~6 hours of work, I did manage to build a modified MIPS version of ECWolf that runs on the RG280V! Very exciting moment, but there were lots of dead ends, and sorting through my thinking will be a challenge. I'll try to capture my thoughts here for later refinement.
- Cross-compilation isn't as magic as I thought. The basic idea is to bootstrap yourself to produce a compiler (and dependencies) that target a different architecture. This is a manual process, and https://github.com/tonyjih/RG350_buildroot proved to be very useful. I ran
make toolchain
and thenmake sdl sdl_image <a bunch of other sdl packages>
. I got the list of packages withmake show-targets
.- This process was broken because the server in France that the build attempts to pull
isl-0.18
from wasn't responding. The file was anxz
file, but I found that by updating the shasum in the package folder forisl
and pointing the server tohttps://gcc.gnu.org/pub/gcc/infrastructure/
got me past this hitch, even though the GNU server uses bz2 for compression. I think CMake knows how to decompress these payloads transparently, since it Just Worked.
- This process was broken because the server in France that the build attempts to pull
- This outputs content to two folders:
output/target
andoutput/host
. I initially usedtarget
for everything, but to make it all work, I ended up binding everything tooutput/host
. This folder contains asysroot
that I can point theecwolf
build to for all its tooling: the C compiler, C++ compiler,ar
tools, etc. - I installed Ubuntu's
mipsel
(this is little-endian 32-bit MIPS, I discovered) build-essential and tried using that, but it builds for Linux and links against libc, and ecwolf on the RG280V needs to useld-uClibc.so.0
, so using the toolchain built for the RG350 was necessary. - I looked into using Qemu and building there, but Qemu was tough to get running, and I don't have a development image for MIPS. I came across the idea in a SO post about cross-compilation. I tried booting into the adam image with
qemu-system-mipsel adam_v1.3.1.img
, but it never initialized the display, so I went back to the cross-compile approach. - To get
ecwolf
to use the toolchain, I ended up doing a bunch of magic:- Use cmake to create a native build. I.e.
cd ecwolf && mkdir build && cd build && cmake ../ && make -j4
. This outputs a file calledImportExecutables.cmake
that needs to be referenced in the MIPS build. I figured this out from reading:- A thread on cross-compilation of ZDoom. The author of ecwolf, Blzut3, commented there and provided just enough info for me to power through.
- Two critical commits on the funkey-s fork of ecwolf:
- This commit shows how to update
IMPORT_EXECUTABLES
. - This commit has the
opk
creation script, as well as tweaks to file_directory.cpp to removefts.h
(which seems to be missing), and defines__sun
, which turned out to be a variable I used to make the compilation work in the end. Specifically, I had problems with the complier not understanding the ifdefs in the file, so I removed all platforms except the path for__sun
, which is how I ultimately got the build I used.
- This commit shows how to update
- Use cmake to create a native build. I.e.
- My initial compiles worked for MIPS (I used
file
to figure out what they were), but were linked againstld.so.0
rather thanld-uClibc.so.0
. I was confused about how to bring in the correct libraries for linking, and ran across this discussion of specifying a sysroot on the ROS forums. This turned out to be a dead-end; my final solution did not require settingsysroot
. - The final executable is dynamically linked. I read through CMake's docs on linking, but haven't figured out the approach here yet.
- The root issue, which relates to ecwolf linking against libbz2, led me down a path of compiling libbz2 myself and dropping it into the Adam image. Because Adam uses squashfs for the root filesystem, I wasn't able to drop the MIPS so into the directory. And because all apps are run with
opkrun
(which mounts the opk on loopback on/opk
to run it), I don't have control overLD_LIBRARY_PATH
at runtime, and no non-system paths are in the equivalent ofld.so.conf
(which OpenDingux doesn't seem to have, but there must be some equivalent, I'm guessing). I tried bundling the libbz2 into the opk directly, but this was not effective. - After completing the native build, and then created a
mipsbuild
directory under ecwolf and ran cmake:mkdir mipsbould && cd mipsbuild && cmake ../
. This produces CMake's best guess about how to run the build, captured in a file called CMakeCache.txt. This file is where I updated all the compiler locations, disabled the extrenal bz2, and generally did a ton of surgery. Once that's set up, runningmake -j4
produced a build in about 30 seconds or so. - I learned a lot about squashfs as part of this. Especially how to unpack and repack opks. The blog I learned about most of this from has a link to a small project the author built that has a target for building the opk as well.
Briefly:
cp /mnt/clonezilla/live/filesystem.squashfs /path/to/workdir
cd /path/to/workdir
unsquashfs filesystem.squashfs
mv filesystem.squashfs /path/to/backup/
cd /path/to/workdir
mksquashfs squashfs-root filesystem.squashfs -b 1024k -comp xz -Xbcj x86 -e boot
I didn't use that last line because I wasn't sure what the options did...they seem to be related to bootability, which I don't care about. Instead used a script from a fork of ecwolf
:
mksquashfs gcw0-assets ecwolf.opk -all-root -noappend -no-exports -no-xattrs -no-progress > /dev/null