The Panic Playdate is a tiny, just-for-fun indie game console.
This post will discuss getting started with ASM on the Panic Playdate.
The Playdate’s CPU is a Cortex M7 that only supports Thumb instructions.
The simulator uses the instruction set of the development machine.
The author has tested ASM in versions of the simulator that run on both
X86_64 and Apple Silicon.
Software Versions
Instructions
Project Template
When ASM is handwritten at all, it is generally used for optimizing native
code.
Therefore, the Hello World C API example will make a reasonable
project template.
Replace the contents of main.c with the following.
This program calculates the distance of a diagonal line according to
the Pythagorean theorem.
The bulk of the code is C, but the square root will be calculated in ASM.
Note that the D-pad, buttons, and crank can be used to control the
distance in different ways.
src/main.c
Add main.h.
src/main.h
Add the fast_sqrt.h header file for the ASM code.
src/fast_sqrt.h
Add a stub fast_sqrt.c implementation.
Change the PRODUCT and SRC lines in the Makefile.
Makefile Partial Listing
Update pdxinfo.
Source/pdxinfo
Finally, build and run the project to make sure it works.
The distance of the diagonal line should be a fixed value of 0.0.
The goal is to calculate that value with ASM.
ASM Square Root Implementations
On modern CPUs, calculating the square root of a number can be done with
a single instruction.
The Cortex M7 uses the ARMv7E-M microarchitecture.
It only supports Thumb instructions.
ARM-Thumb interworking is not possible on the Playdate.
The Thumb ASM for a square root subroutine that will run on hardware follows.
src/fast_sqrt_armv7.s
The MacBook Pro this post is being typed up on runs on an Apple M1 Max.
It uses the ARMv8.5-A instruction set.
The Apple Silicon cores only support 64-bit ARM instructions.
Thumb is a thing of the past, and 32-bit ARM instructions are not supported
either.
The ARMv8 ASM for a square root subroutine that will run on the simulator
follows.
src/fast_sqrt_armv8.s
The author first experimented with ASM on Playdate using a machine that runs
x86-64 instructions.
This is the ASM for a simulator subroutine that runs on a 64-bit Intel
processor.
src/fast_sqrt_x86_64.s
Makefile Modifications
The Playdate Makefiles look like they were written with ASM, but a few
modifications need to be made to properly build the project.
First, the ASM for the device and simulator need to be listed separately.
Update SRC and add ASRC definitions in the Makefile.
Uncomment the ASRC_SIMULATOR definition for your development platform.
Also, update the last line of the Makefile for the next step.
Makefile
Playdate Makefiles rely on some common machinery that does not entirely
support ASM code.
The ${PLAYDATE_SDK_PATH}/C_API/buildsupport/common.mk file could be
modified directly, but it is better to keep the modified copy in the project.
Copy common.mk into the project.
Three modifications need to be made to the local common.mk.
ASRC_DEVICE needs to be appended to _OBJS, and ASRC_SIMULATOR
needs to be appended to the $(OBJDIR)/pdex.${DYLIB_EXT} target.
Finally, the pdc target needs to rely on the device so that a
functional copy of pdex.bin is always included in the “fat” PDX file.
(Hardware runs pdex.bin while the simulator uses a dynamic library,
pdex.dylib on macOS.)
The following diff gives a guide to the changes that need to be made to
common.mk.
Rebuild the project.
If all goes well, the diagonal distance should be calculated and updated in
realtime.
The program will automatically resize the rectangle if the crank is docked.
Undock the crank for manual control and verification.
Running on Hardware
To upload a PDX file to hardware, first, run it in the simulator.
Then either “Upload Game to Device” from the “Device” menu or Playdate icon on
the lower lefthand corner of the simulator (with the crank controls collapsed).
Once the game is on the device, pdutil can be used to launch it.
Alternatively, pdutil can be used to directly upload the game to hardware
from the command line.
Note that the author could not get the following code to reliably work in
a script because it takes time for the Playdate to become available after
it is mounted in datadisk mode.
Verification
Pull out the crank and use the D-pad to move the lower righthand point to
(100, 75). The diagonal length should be 125.000. Use a calculator to
verify other sets of values.