I’ve decided to go with putting Unreal Engine 5 on the Wii for my dissertation!
The Toolchain
I followed devkitpro’s installation guide so I now have everything available through pacman. Installing the Wii stuff was super easy on Arch! I now have the PowerPC toolchain (including a gcc/g++ compiler), a bunch of wii examples, cmake files, and several tools!
CMake Wii Hello World
To get my feet a little wet I’ll grab the cmake example to see if I can get cmake working. Although Unreal uses it’s own custom build system, understanding how CMake is setup will probably help us understand what’s required when building Wii applications.
The example does not work out of the box with the ol’ reliable: cmake -S . -B build
CMake Error at CMakeLists.txt:17 (ogc_create_dol):
Unknown CMake command "ogc_create_dol".So let’s read the CMakeLists.txt:
cmake_minimum_required(VERSION 3.13)
project(application LANGUAGES C VERSION 1.0.0)
add_executable(${PROJECT_NAME})
target_sources(${PROJECT_NAME} PRIVATE
source/main.c
)
target_compile_options(${PROJECT_NAME} PRIVATE -Wall)
target_include_directories(${PROJECT_NAME} PRIVATE
include
)
ogc_create_dol(${PROJECT_NAME})I have two questions:
- How do we know to use the PowerPC compiler?
- wtf is
ogc_create_doland where do I find it?
Question 1: How do we know to use the PowerPC compiler?
Let’s read up on cross compiling with CMake. Looks like we need to make a toolchain file which sets all the necessary variables such as which compiler to use, system name, etc. We can then specify this file by setting CMAKE_TOOLCHAIN_FILE. Chances are this toolchain file already exists in $DEVKITPRO/cmake:
Catnip/ dkp-catnip-utils.cmake dkp-initialize-path.cmake ogc-common.cmake
catnip-main.cmake dkp-custom-target.cmake dkp-linker-utils.cmake Platform/
devkitPPC.cmake dkp-embedded-binary.cmake dkp-rule-overrides.cmake Wii.cmake
dkp-asset-folder.cmake dkp-impl-helpers.cmake* dkp-toolchain-common.cmake$DEVKITPRO/cmake/devkitPPC.cmake
include(${CMAKE_CURRENT_LIST_DIR}/dkp-initialize-path.cmake)
include(dkp-toolchain-common)
set (DKP_BIN2S_ALIGNMENT 32)
__dkp_toolchain(devkitPPC ppc powerpc-eabi)
set(DKP_INSTALL_PREFIX_INIT ${DEVKITPRO}/portlibs/ppc)This looks like it could be it!
$DEVKITPRO/cmake/Wii.cmake
cmake_minimum_required(VERSION 3.13)
if(NOT CMAKE_SYSTEM_NAME)
set(CMAKE_SYSTEM_NAME NintendoWii)
endif()
include(${CMAKE_CURRENT_LIST_DIR}/ogc-common.cmake)CMAKE_SYSTEM_NAME is also something set in a toolchain file…
$DEVKITPRO/cmake/ogc-common.cmake
cmake_minimum_required(VERSION 3.13)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoWii")
set(OGC_CONSOLE wii)
set(OGC_SUBDIR wii)
set(OGC_MACHINE rvl)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoGameCube")
set(OGC_CONSOLE gamecube)
set(OGC_SUBDIR cube)
set(OGC_MACHINE ogc)
else()
message(FATAL_ERROR "Unsupported libogc platform")
endif()
# Import devkitPPC toolchain
include(${CMAKE_CURRENT_LIST_DIR}/devkitPPC.cmake)
set(OGC_ROOT ${DEVKITPRO}/libogc)
set(DKP_INSTALL_PREFIX_INIT ${DEVKITPRO}/portlibs/${OGC_CONSOLE})
__dkp_platform_prefix(
${DEVKITPRO}/portlibs/${OGC_CONSOLE}
${DEVKITPRO}/portlibs/ppc
${OGC_ROOT}
)
find_program(PKG_CONFIG_EXECUTABLE NAMES powerpc-eabi-pkg-config HINTS "${DEVKITPRO}/portlibs/${OGC_CONSOLE}/bin")
if (NOT PKG_CONFIG_EXECUTABLE)
message(FATAL_ERROR "Could not find powerpc-eabi-pkg-config: try installing ${OGC_CONSOLE}-pkg-config")
endif()
find_program(ELF2DOL_EXE NAMES elf2dol HINTS "${DEVKITPRO}/tools/bin")
find_program(GCDSPTOOL_EXE NAMES gcdsptool HINTS "${DEVKITPRO}/tools/bin")
find_program(GXTEXCONV_EXE NAMES gxtexconv HINTS "${DEVKITPRO}/tools/bin")Ahhhhh of course. The Wii and the Gamecube are both PowerPC devices which devkitpro supports! So let’s see what happens when I set CMAKE_TOOLCHAIN_FILE to $DEVKITPRO/cmake/Wii.cmake
sam@rustbucket ~/s/application> cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$DEVKITPRO/cmake/Wii.cmake
-- The C compiler identification is GNU 15.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /opt/devkitpro/devkitPPC/bin/powerpc-eabi-gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Configuring done (0.1s)
-- Generating done (0.0s)
-- Build files have been written to: /home/sam/src/application/build
sam@rustbucket ~/s/application> cmake --build build
[ 50%] Building C object CMakeFiles/application.dir/source/main.o
[100%] Linking C executable application.elf
Converting application to .dol format
[100%] Built target applicationThat’s done it! We have a build!
Question 2: wtf is ogc_create_dol and where do I find it?
Well fortunately the second half of this question has already been answered. It’s included in the OGC cmake files which our Wii.cmake toolchain file includes for us.
But what does it do? The build seems to link to a .elf file and then right at the end that gets converted to a .dol file.
What are these filetypes?
ELF
From wiki.osdev.org:
ELF (Executable and Linkable Format) was designed by Unix System Laboratories while working with Sun Microsystems on SVR4 (UNIX System V Release 4.0). Consequently, ELF first appeared in Solaris 2.0 (aka SunOS 5.0), which is based on SVR4. The format is specified in the System V ABI.
A very versatile file format, it was later picked up by many other operating systems for use as both executable files and as shared library files. It does distinguish between TEXT, DATA and BSS.
Today, ELF is considered the standard format on Unix-alike systems. While it has some drawbacks (e.g., using up one of the scarce general purpose registers of the IA-32 when using position-independent code), it is well supported and documented.
From wiibrew.org:
This format is supported by many Wii homebrew loading techniques, particularly the Homebrew Channel, although most methods also support Nintendo’s .dol format, and some methods only support one or the other.
DOL
From wiibrew.org:
The Dol file format is the main executable file format for both the GameCube and the Wii. The name presumably refers to “Dolphin”, which was the GameCube’s codename. It is a simple file format consisting of a header and up to 7 loadable code sections (Text0..Text6) and up to 11 data sections (Data0..Data10). All values in the header are unsigned big-endian 32-bit values.
Additional Observations
The .ELF file is significantly larger than the .DOL file (1.6Mib vs 325KiB). So .DOL really is simple! Both seem to run fine on Dolphin